问题描述
当我尝试通过共享指针访问类的成员时,我遇到了一个问题。
程序运行良好并给出了预期的输出:"Name: Michel"
。但是当我注释标记为 COMMENT_THIS_LINE
的行时,它给出了一些垃圾值而不是 Michel
。任何人都可以解释这种行为,以及如何在没有标记线的情况下获得正确的输出?
class TestShared{
public:
TestShared(std::string name);
std::string getName(void);
private:
std::string m_name;
};
class Another{
public:
const char *name;
};
TestShared::TestShared(std::string name) : m_name(name)
{
}
std::string TestShared::getName(void)
{
return m_name;
}
std::shared_ptr<TestShared> allocate_ts()
{
char p[] = "Michel";
return std::make_shared<TestShared>(p);
}
Another GetAnother(std::shared_ptr<TestShared> ts)
{
Another an;
std::string a = ts->getName(); //////////COMMENT_THIS_LINE
an.name = ts->getName().c_str();
return an;
}
int main()
{
std::shared_ptr<TestShared> ts = allocate_ts();
Another an = GetAnother(ts);
printf("Name: %s\n",an.name);
return 0;
}
解决方法
重要的一点是:
std::string TestShared::getName(void)
{
return m_name;
}
还有这个:
Another an;
an.name = ts->getName().c_str(); // (*)
return an;
getName()
返回私有字符串的副本。 c_str()
返回一个指向该临时文件的内部字符数组的指针。 an.name
存储该指针,该指针已经悬挂在 ;
中的 (*)
处。
您需要复制字符串,或者当您真正需要 char*
时,不要使用 string
指针。
从 m_name
返回对成员 getName()
的引用也可以解决当前的问题,但是如果您希望 an.name
存储一个字符串,您实际上应该存储一个字符串,而不仅仅是指向其他字符串的内部缓冲区的指针。
您的代码有未定义的行为,因为当您通过 printf("Name: %s\n",an.name);
打印字符串时,指针不再有效。它指向的 string
早已不复存在。未定义的行为可能会产生奇怪的效果,例如添加一条看似无关的行来改变行为。当存在额外的代码行时,不要被产生预期输出的代码误导。这只是一个副作用,您的代码是错误的,即使它看起来有效。