Kyl*_*yle 157 c++ temporary const-reference ctor-initializer
为什么这样:
#include <string>
#include <iostream>
using namespace std;
class Sandbox
{
public:
Sandbox(const string& n) : member(n) {}
const string& member;
};
int main()
{
Sandbox sandbox(string("four"));
cout << "The answer is: " << sandbox.member << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
给出输出:
答案是:
代替:
答案是:四
Pot*_*ter 154
只有本地 const
参考才能延长使用寿命.
该标准在§8.5.3/ 5 [dcl.init.ref]中指定了这种行为,这是关于参考声明的初始化者的部分.示例中的引用绑定到构造函数的参数n
,并且当n
绑定对象超出范围时变为无效.
生命周期扩展不是通过函数参数传递的.§12.2/ 5 [class.temporary]:
第二个上下文是引用绑定到临时的.除了下面指定的内容之外,引用绑定的临时对象或作为临时绑定对象的子对象的完整对象的临时对象的生命周期仍然存在.绑定到构造函数的ctor-initializer(第12.6.2节[class.base.init])中的引用成员的临时绑定将持续存在,直到构造函数退出.在函数调用(第5.2.2节[expr.call])中对引用参数的临时绑定将持续存在,直到包含该调用的完整表达式完成为止.
Squ*_*ama 24
这是解释发生事情的最简单方法:
在main()中,您创建了一个字符串并将其传递给构造函数.此字符串实例仅存在于构造函数中.在构造函数中,您指定成员直接指向此实例.当scope离开构造函数时,字符串实例被销毁,然后成员指向不再存在的字符串对象.让Sandbox.member指向其范围之外的引用将不会在范围内保存这些外部实例.
如果要修复程序以显示所需的行为,请进行以下更改:
int main()
{
string temp = string("four");
Sandbox sandbox(temp);
cout << sandbox.member << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在temp将在main()的末尾而不是在构造函数的末尾超出范围.但是,这是不好的做法.您的成员变量永远不应该是对实例外部存在的变量的引用.在实践中,您永远不知道该变量何时超出范围.
我建议将Sandbox.member定义为a const string member;
将临时参数的数据复制到成员变量中,而不是将成员变量指定为临时参数本身.
从技术上讲,这个程序不需要实际输出任何东西到标准输出(这是一个缓冲流)。
该cout << "The answer is: "
位将发送"The answer is: "
到stdout的缓冲区中。
然后该<< sandbox.member
位将提供悬空引用到 中operator << (ostream &, const std::string &)
,这会调用未定义的行为。
正因为如此,什么都不能保证发生。该程序可能看起来运行良好,或者可能在没有刷新标准输出的情况下崩溃——这意味着文本“答案是:”不会出现在您的屏幕上。
归档时间: |
|
查看次数: |
44747 次 |
最近记录: |