考虑以下代码:
class Foo
{
private:
const string& _bar;
public:
Foo(const string& bar)
: _bar(bar) { }
const string& GetBar() { return _bar; }
};
int main()
{
Foo foo1("Hey");
cout << foo1.GetBar() << endl;
string barString = "You";
Foo foo2(barString);
cout << foo2.GetBar() << endl;
}
当我执行此代码时(在VS 2013中),该foo1
实例的_bar
成员变量中包含一个空字符串,而foo2
的相应成员变量中包含对值“ You”的引用。这是为什么?
更新:在这个示例中,我当然使用了std :: string类。
对于Foo foo1("Hey")
编译器必须执行从const char[4]
到的转换std::string
。它创建一个类型的prvalue std::string
。该行等效于:
Foo foo1(std::string("Hey"));
引用绑定从prvalue到发生bar
,然后另一个引用绑定从bar
到发生Foo::_bar
。这里的问题在于,这std::string("Hey")
是一个临时对象,当它出现在其中的完整表达式结束时会被销毁。也就是说,在分号之后std::string("Hey")
将不存在。
这会导致悬空引用,因为您现在已经Foo::_bar
引用了已被销毁的实例。当您打印字符串时,使用悬挂引用会导致未定义的行为。
该行Foo foo2(barString)
很好,因为barString
初始化后存在foo2
,所以Foo::_bar
仍引用的有效实例std::string
。由于初始化程序的类型与引用的类型匹配,因此不会创建临时文件。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句