【问题标题】:C++ references and exiting scopingC++ 引用和退出范围
【发布时间】:2020-04-01 07:40:00
【问题描述】:

我开始掌握 C++ 中的引用,并且我有一个关于引用和范围的小查询,为此最好创建一个示例:

假设我在“BankDatabase.cpp”中有一个方法,它通过引用获取银行记录并将其添加到数据结构中(也通过引用)。

void AddRecord( BankRecord& bankRecord )
{
    //Add record to data structure by reference
}

如果我运行这样的方法:

void TestAddRecord( BankDatabase& bankDatabase )
{
    BankRecord bankRecord { "John", "Doe", 9999 }
    bankDatabase.AddRecord( bankRecord );
}

在我看来,“bankRecord”超出了范围(就像它的两个字符串和 int 一样),因此在“TestAddRecord”方法结束时从内存中清除,让“bankDatabase”指向一些空内存?

如果是这样,对于这种情况,普遍接受的标准/解决方案是什么?必须按值传递东西似乎有点疯狂......

【问题讨论】:

    标签: c++ pointers memory memory-management scope


    【解决方案1】:

    在这种情况下,按值传递似乎是要走的路。分配一个新的BankRecord 指针也可以。通过引用存储东西不是很好。

    但是,如果我没记错的话,您的两个字符串和 int 不会丢失,因为它们存在于堆栈中并且不会被释放。但是bankRecord 仍然会丢失。

    【讨论】:

    • 我担心它似乎不是特别灵活,所以例如,如果我要添加两次记录 - bankDatabase.AddRecord(bankRecord); bankDatabase.AddRecord(bankRecord); - 那么他们应该共享一个引用,但给出一个“按值传递”他们不会?
    • @PaulRenton 哦,好的!我一直认为引用是指针的糖,这几乎不是错误的。所以我们需要知道存储数据结构来判断引用是否被复制?
    • 是的,例如,如果 AddRecord 有几个覆盖,就像许多常见的数据结构一样。如果 AddRecord 的签名看起来像这样 - AddRecord( varType object && ),它将使用移动语义并且不会像典型的按值传递附加可能那样多次调用构造函数。此外,一些数据结构在内部进行 POD 数据检查,然后只进行 memcopy。有时,挑战您的假设并单步执行代码以查看会发生什么是非常重要的。这是一个很好的做法。
    • @D.Nathanael 如果您想查看我所说的示例,请查看向其中添加元素的所有 std::vector 函数。首先查看 emplace、push_back 和其他之间的区别。
    • @D.Nathanael 最后一件事值得一提。指针和引用之间的一个很大区别是,对对象的引用只能分配一个而不能分配给 nullptr(除非您执行邪恶的技巧)。一旦将引用分配给 r 值,它将使用所有对象运算符,包括赋值运算符,正如您可能猜到的那样,它将改变事情的工作方式,而不是将指针传递到上面的数据结构中将同一指针从一个对象分配给另一个对象时,运算符不适用。希望这会有所帮助
    【解决方案2】:

    回答这些问题的最佳方法是在调试器中单步调试代码,并查看 Vector 对附加变量的作用。当您进入数据结构的 Append 函数时,请特别注意构造函数调用。因为我不知道你的底层数据结构,所以告诉你更多信息对我来说有点困难。我暂时假设它是一个 std::vector ,直到另有说明。

    您可能会惊讶地发现,通过函数传递的引用并不能说明它何时进入和离开范围的全部内容。我经常将 C++ 引用视为不需要 nullptr 检查的指针。

    只要引用被复制到向量中或不会因为它指向的变量被破坏而超出范围,您的代码就可以正常工作。如果引用在特定情况下引用堆上的成员变量或内存,则引用不会超出范围。

    如果在堆栈上声明了对在堆栈上创建的变量的引用,然后将其附加到向量,那么您将遇到范围问题。

    如果你有 C++11 并且编译器支持移动语义,你也应该查看 emplace()。

    简而言之,您可以在这里做的最重要的事情是单步调试代码并查看调用了哪些构造函数。这会给你想要的答案。

    【讨论】:

      猜你喜欢
      • 2012-12-24
      • 1970-01-01
      • 2020-11-25
      • 2013-02-25
      • 1970-01-01
      • 1970-01-01
      • 2021-06-20
      • 2013-08-12
      • 1970-01-01
      相关资源
      最近更新 更多