为什么这样做:

#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;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top