[英]c++ passing a string literal instead of a const std::string&?
I have the following code which compiles with no warnings (-Wall -pedantic) with g++ 我有以下代码,使用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;
}
But when I run it, only the newline is printed out. 但是当我运行它时,只打印出换行符。 What is going on? 到底是怎么回事?
If I were to do this inside stuff: 如果我要在里面做这件事:
string temp("snoop");
Foo f(temp);
f.print();
then it works fine! 然后它工作正常!
The reason why this fails is because it essentially compiles to the following under the hood. 这种失败的原因是因为它基本上编译成了以下内容。
Foo o(std::string("wurd"));
In this case the Foo
value is taking a reference to a temporary object which is deleted after the constructor completes. 在这种情况下, Foo
值引用一个临时对象,该对象在构造函数完成后被删除。 Hence it's holding onto a dead value. 因此它保持了死亡价值。 The second version works because it's holding a reference to a local which has a greater lifetime than the Foo
instance. 第二个版本有效,因为它持有对具有比Foo
实例更长寿命的本地的引用。
To fix this change the memebr from being a const std::string&
to a const std::string
. 要解决此问题,请将memebr从const std::string&
更改为const std::string
。
Whats happening is that the reference 'str' is being initialized so that it points to the temporary arg, 's'. 发生的事情是,引用'str'正在被初始化,以便它指向临时arg,'s'。 Its pretty much the same as using a pointer - you're counting on the continued existence of your constructor arg, 's'. 它与使用指针几乎相同 - 你依赖于构造函数arg的继续存在,'s'。 When the temporary is deleted (after the constructor ftn returns), then your reference now points at garbage. 删除临时值(在构造函数ftn返回之后),那么您的引用现在指向垃圾。
To fix, change str so that its an actual string object and not a reference. 要修复,请更改str以使其成为实际的字符串对象而不是引用。
const std::string str; const std :: string str;
That way a copy will be made of your arg string, and said copy will have the same lifespan as your Foo object. 这样一个副本将由你的arg字符串组成,并且所述副本将与你的Foo对象具有相同的生命周期。
Extending on the answers given before: If you want to avoid the copy of the data, you can change the member and constructor parameter of Foo to const char*
. 扩展之前给出的答案:如果要避免复制数据,可以将Foo的成员和构造函数参数更改为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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.