const参考类成员会延长暂时的寿命吗?
-
03-10-2019 - |
题
为什么这样做:
#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;
}
给出:
答案是:
代替:
答案是:四个
解决方案
仅有的 当地的 const
参考文献延长了寿命。
该标准在第8.5.3/5节中指定了这种行为,[dcl.init.ref],有关参考声明初始化的部分。您的示例中的引用与构造函数的参数绑定 n
, ,当对象时变得无效 n
一定会超出范围。
生命周期扩展不是通过函数参数传递的。 §12.2/5 [class.temporary]:
第二个上下文是当引用绑定到临时性时。引用是绑定的临时或临时对象的临时对象,该子对象的临时界限持续存在于参考的生命周期,除非指定。在构造函数ctor-Inializer(§12.6.2[class.base.init])中,临时与参考构件绑定在一起,直到构造函数退出为止。临时绑定到函数调用(第§5.2.2[expr.call])中的参考参数,直到完成包含调用的完整表达式完成。
其他提示
这是解释发生的事情的最简单方法:
在main()中,您创建了一个字符串并将其传递到构造函数中。此字符串实例仅存在于构造函数中。在构造函数内部,您将成员分配给直接指向此实例。当范围离开构造函数时,字符串实例被破坏,然后成员指向不再存在的字符串对象。在其范围之外,将SandBox.Member指向参考将不会将这些外部实例固定在范围中。
如果要修复程序以显示所需的行为,请进行以下更改:
int main()
{
string temp = string("four");
Sandbox sandbox(temp);
cout << sandbox.member << endl;
return 0;
}
现在,温度将在main()的末端而不是在构造函数的末端脱离范围。但是,这是不好的做法。您的成员变量绝不应该是对实例之外存在的变量的引用。实际上,您永远不知道该变量何时会超出范围。
我推荐的是将sandbox.member定义为 const string member;
这将将临时参数的数据复制到成员变量中,而不是将成员变量分配为临时参数本身。
从技术上讲,该程序实际上不需要实际输出任何内容到标准输出(这是一个开始的缓冲流)。
这
cout << "The answer is: "
位会发出"The answer is: "
进入 缓冲 Stdout。然后
<< sandbox.member
位会提供悬空的参考operator << (ostream &, const std::string &)
, ,调用 不确定的行为.
因此,没有任何保证会发生。该程序可能工作正常,或者甚至可能不会碰撞,甚至可能会崩溃 - 这意味着文字“答案是:”不会出现在屏幕上。
因为一旦返回沙盒构造函数,您的临时绳子就会脱离范围,并且用于其他目的的堆栈被占用。
通常,您绝对不要长期保留参考文献。参考对于参数或本地变量有益,从不班级成员。
您指的是消失的东西。以下将有效
#include <string>
#include <iostream>
class Sandbox
{
public:
const string member = " "; //default to whatever is the requirement
Sandbox(const string& n) : member(n) {}//a copy is made
};
int main()
{
Sandbox sandbox(string("four"));
std::cout << "The answer is: " << sandbox.member << std::endl;
return 0;
}