我有以下代码,使用g ++编译没有警告(-Wall -pedantic)
#include <iostream>
#include <string>
using namespace std;
class Foo
{
public:
Foo(const std::string& s) : str(s)
{ }
void print()
{
cout << str << endl;
}
private:
const std::string& str;
};
class Bar
{
public:
void stuff()
{
Foo o("werd");
o.print();
}
};
int main(int argc, char **argv)
{
Bar b;
b.stuff();
return 0;
}
但是当我运行它时,只打印出换行符。 发生了什么?
如果我要在里面做这件事:
string temp("snoop");
Foo f(temp);
f.print();
然后它运作正常!
答案 0 :(得分:21)
这种失败的原因是因为它基本上可以编入以下内容。
Foo o(std::string("wurd"));
在这种情况下,Foo
值将引用一个临时对象,该对象在构造函数完成后被删除。因此它保持了死亡价值。第二个版本有效,因为它持有对具有比Foo
实例更长寿命的本地的引用。
要修改此更改,请将memebr从const std::string&
更改为const std::string
。
答案 1 :(得分:2)
发生的事情是,正在初始化引用'str',以便它指向临时arg,'s'。它与使用指针几乎相同 - 你依赖于构造函数arg的继续存在,'s'。删除临时值(在构造函数ftn返回之后),那么您的引用现在指向垃圾。
要修复,请更改str以使其成为实际的字符串对象而不是引用。
const std :: string str;
这样就会复制你的arg字符串,并且所说的副本将与你的Foo对象具有相同的生命周期。
答案 2 :(得分:0)
扩展之前给出的答案:如果要避免复制数据,可以将Foo的member和constructor参数更改为const char*
。
class Foo
{
public:
Foo(const char* s) : str(s)
{ }
void print()
{
cout << str << endl;
}
private:
const char* str;
};
class Bar
{
public:
void stuff()
{
Foo o("werd");
o.print();
}
};
int main(int argc, char **argv)
{
Bar b;
b.stuff();
return 0;
}