C++ 通过引用传递与通过指针传递时对象的范围

C++ 通过引用传递与通过指针传递时对象的范围,c++,memory-management,destructor,C++,Memory Management,Destructor,考虑下面的简单代码 struct test { test(int n):numelements(n){ arr = new int[numelements] } int numelements; int* arr; ~test() { delete[] arr; } } void foo_ref(test& x,n) { // set

考虑下面的简单代码

    struct test
    {
      test(int n):numelements(n){ arr = new int[numelements] }

      int numelements;
      int* arr;

      ~test()
       {
          delete[]  arr;
       }
    }

   void foo_ref(test& x,n)
   {
       // set first n elements of the array x.arr to random numbers
   }

  void foo_ptr(test* x,n)
   {
       // set first n elements of the array x->arr to random numbers
   }

    int main(void)
    {
     test mystruct(1000000);
     foo_ref(mystruct,20);
     // foo_ptr(&mystruct,20); 


     return 0;
   }
在上述代码中,
foo_ref
foo_ptr
对执行完全相同的操作 它所指的对象,即<代码>mystruct。但是foo_ref通过引用传递对象 和foo_ptr通过指针

在这两种情况下,调用对象的析构函数在哪里?我知道这个问题的标准答案总是“当对象的范围结束时”

<>但是考虑通过引用的情况。在
foo_ref
mystruct具有该功能的范围。那么,在函数
foo_ref
的末尾不会调用对象的析构函数吗

也许我的困惑与对事物范围的理解有关。
请让我知道我的推理哪里出错了

我在这里没有看到任何
const
引用,因此答案是“引用和指针之间的对象生存期没有区别”

const
绑定到临时表达式的引用具有延长临时对象生存期的特殊规则,但这不适用于您的代码


你的困惑可能源于,它沿着“引用就是被引用的对象”的思路。正如你所看到的,这不是真的。一个引用与它引用的对象是分开的,每个引用都有自己的生命周期(很难看到这样做是正确的,但是引用的生命周期比对象的生命周期更长是合法的)

我在这里没有看到任何
const
引用,因此答案是“引用和指针之间的对象生存期没有区别”

const
绑定到临时表达式的引用具有延长临时对象生存期的特殊规则,但这不适用于您的代码


你的困惑可能源于“引用就是被引用的对象”。正如你所看到的,这不是真的。引用与它所引用的对象是分开的,每个对象都有自己的生命周期(很少有人能正确地执行此操作,但引用的生存期延长到比对象的生存期更长甚至是合法的)
foo_ref
将有一个参数,该参数将具有函数的作用域。它是指针还是引用都不会对mystruct的删除产生任何影响


在按值传递结构的情况下,副本将在函数末尾被销毁。如果在副本中引用相同的arr,则可能会在原始结构仍在使用时意外删除arr。在这种情况下,您可能希望使用共享指针来跟踪arr使用的内存手动删除它。

foo_ref
将有一个参数,该参数将具有函数的范围。它是指针还是引用都不会对mystruct的删除产生任何影响


在按值传递结构的情况下,副本将在函数末尾被销毁。如果在副本中引用相同的arr,则可能会在原始结构仍在使用时意外删除arr。在这种情况下,您可能希望使用共享指针来跟踪arr使用的内存在示例代码中,
mystruct
的析构函数在
main
的末尾被调用

指针当指针超出范围时,所指向的对象不会发生任何变化。如果指针不存在,对象的生命周期将保持不变。当然,还有一个重要的细节:由
new
/
new[]创建的对象
存在,直到
delete
d/
delete[]
d,并且
malloc
分配的内存存在,直到
空闲
d

引用引用只不过是现有对象的附加名称。除了指向临时对象的
const
引用外,引用的生存期对被引用对象的生存期没有影响;当该对象超出正常范围时,会调用析构函数(对临时对象的
const
引用使临时对象保持活动状态,直到
const
引用超出范围)

,指针或引用实际上指向内存;它不会以任何方式“跟踪”实际对象。例如,可以在指针超出范围之前销毁指向的对象,或在引用超出范围之前销毁引用的对象。这些无效指针/引用被调用“分别为“悬挂指针”和“悬挂引用”:

int* i = new int(5);
int& j = *i;
delete i;

// i is now a dangling pointer, and j is now a dangling reference

在示例代码中,
mystruct
的析构函数在
main
的末尾调用

指针当指针超出范围时,所指向的对象不会发生任何变化。如果指针不存在,对象的生命周期将保持不变。当然,还有一个重要的细节:由
new
/
new[]创建的对象
存在,直到
delete
d/
delete[]
d,并且
malloc
分配的内存存在,直到
空闲
d

引用引用只不过是现有对象的附加名称。除了指向临时对象的
const
引用外,引用的生存期对被引用对象的生存期没有影响;当该对象超出正常范围时,会调用析构函数(a
const
对临时对象的引用使临时对象保持活动状态,直到
const