传递给存储常量引用的成员的临时对象的生命周期

时间:2014-01-18 14:35:02

标签: c++ reference

假设我有一个对象Obj和一个Set。该集正在收集const Obj&数组中的引用。实际的Obj可以使用多长时间:

{
    Set s;
    s.add(Obj(...));
    s.add(Obj(...));

    s.doWhateverWithTheObjs();

}
// after this it's guaranteed to not work anymore, if s was on the heap. Obj's will die with stack

我还没有实现,因为我首先要确认这实际上是可行的。

我知道当Set在堆上时它不起作用,它的生命周期比调用者的生命周期长(我用括号来说明这一点)。

我不知道最后一个方法是否仍然可以读取对象的访问权限?在Set中按值存储实际对象将不起作用,因为Obj是多态的。如果可能,我不想出于可用性原因使用指针。

2 个答案:

答案 0 :(得分:0)

只要你在函数内部,除非你复制s.add内的对象(根据你的问题,你没有复制(Set正在收集数组中的const Obj&引用)。 / p>

第二个想法,即使在函数期间也没有,因为在调用Obj期间,每个s.add(Obj(...));实例都在暂时函数的堆栈上分配。

换句话说,不要这样做(你必须复制s.add内的对象。)

<强>补充:

使用const Obj&amp; amp;数组中的引用,但你必须在某处分配实际的实例,无论是在堆上,还是在数据部分(作为全局变量)......或者在调用函数的堆栈上(作为局部变量),如果你'不要在功能之外使用它们。

答案 1 :(得分:0)

  

我不知道最后一种方法是否仍然可以读取对象的访问权限?

该标准定义了两个案例,其中临时的生命周期延长,见§12.2/ 4:

  

第一个上下文是调用默认构造函数来初始化数组的元素。如果构造函数有一个或多个默认参数,则在构造下一个数组元素(如果有)之前,对默认参数中创建的每个临时文件的销毁进行排序。

应该允许初始化数组。第二个更值得关注的是与引用(§12.2/ 5)相关联:

  

第二个上下文是当引用绑定到临时时.118引用绑定的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生存期内持续存在。 :

如您所见,如果临时对象与引用绑定,则对象的生命周期将延伸到引用的生命周期。在“except:”之后列出:

  

在函数调用(5.2.2)中对引用参数的临时绑定一直持续到包含该调用的完整表达式完成为止。

这基本上说,无论你如何定义add的函数体,如果add的签名是T add(const Obj&)(任何T),那么临时对象将在对该函数的调用结束时销毁。这意味着:

s.add(Obj(...));

临时对象将在函数执行结束时被销毁。

因此,出于以上原因:没有。它仍然不具有对象的读访问权。您将获得对已释放对象的引用。


  

在Set中按值存储实际对象将不起作用,因为Obj是多态的。

您可以拥有多态行为并仍然保留对象。例如,您可以使用std::vector std::unique_ptr<Obj>。新对象的创建将如下所示:

vector.emplace_back(std::unique_ptr<Obj>(new Derived()));

你将拥有一个存储值的多态矢量。