常量引用作为类成员

11

即使在这里讨论了很多次,我也找不到关于我的特殊情况的确定性解释。 const 是否会延长 RefTest 临时对象的生命周期?下面的示例是否合法?

#include <iostream>

class RefTest
{
public:
    RefTest(const std::string &input) : str(input) {}
    ~RefTest () {std::cout << "RefTest" << std::endl;}
private:
    std::string str;
};

class Child
{
public:
    Child (const RefTest &ref) : ref_m(ref) {}
    ~Child () {std::cout << "Test" << std::endl;}
private:
    const RefTest &ref_m;
};

class Test
{
public:
    Test () : child(RefTest("child")) {}//Will the temporary get destroyed here?
    ~Test () {std::cout << "Test" << std::endl;}
private:
    const Child child;
};

int main ()
{
   Test test;
}

5
最后一行根本没有创建对象,而是声明了一个函数。请参阅http://en.wikipedia.org/wiki/Most_vexing_parse。 - Oliver Charlesworth
@OliCharlesworth 哦,糟糕。我担心这个例子很蠢:( 请看看我的更新版本,应该更接近我的实际情况。这一次,我不认为会有任何令人烦恼的解析问题。 - Mihai Todor
@NayanaAdassuriya,你指的是哪个test2?我已经重写了我的初始示例,因为我没有充分考虑它。 - Mihai Todor
@carleeto 是的,Haroogan已经链接了。谢谢。 - Mihai Todor
2个回答

12

该引用并不会延长生命周期。该代码是合法的,但仅因为您在构造函数完成后从未访问ref_m

临时对象绑定到构造函数参数ref。稍后将另一个引用绑定到它,ref_m,并不能延长其寿命。如果能够延长它的生命周期,你将在堆栈上有一个对象,在引用成员绑定它的同时必须持久存在,这可能会被分配在堆上,因此当构造函数返回时,编译器将无法展开堆栈。

很高兴能够得到警告,但编译器并不完美,有些事情很难预警。 临时对象在与绑定到引用的上下文中创建,因此编译器只能在开启内联或某些巧妙的静态分析时才能发现问题。


哦,该死。我没有想到它会绑定到函数参数而不是内部成员。感谢您指出这一点。 - Mihai Todor
即使在子构造函数中创建一个临时对象,例如 ref_m(RefTest("")),它也不会延长其生命周期超过构造函数的结束,原因是该临时对象位于构造函数的堆栈帧中,并且必须在该函数返回时被销毁。标准明确规定:“在构造函数的 ctor-initializer (12.6.2) 中绑定到引用成员的临时对象将持续到构造函数退出。” 12.2 [class.temporary] - Jonathan Wakely
的确,我在这里看到的大多数与我的问题相关的答案都是误导性的。 我的理解是,如果我将一个临时变量分配给const引用,那么对象仅在引用超出范围后才会被销毁,而不是临时变量本身。 - Mihai Todor

10
C++标准规定:

第二种情况是当引用绑定到临时对象时。引用所绑定的临时对象或完整对象的子对象,与其绑定的临时对象持续存在于引用的生命周期中,除非以下情况另行规定:在构造函数初始化列表(12.6.2)中引用成员绑定的临时对象将持续到构造函数退出。 在函数调用中引用参数绑定的临时对象(5.2.2)将持续到包含该调用的完整表达式完成。

注意:顺便说一下,这是重复的 (1, 2),下次搜寻时应该更仔细... :)

是的,现在很清楚了。谢谢你引用标准。 - Mihai Todor
感谢编辑中提供的参考。这个话题在这里有太多的问题,现在我可以理解为什么了......大部分让我觉得将临时变量赋值给const引用会延长其生命周期直到该引用超出作用域。 - Mihai Todor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接