通过共享指针访问类成员

iGR*_*GRJ 0 c++ c++11

当我尝试通过共享指针访问类的成员时,我遇到了一个问题。

该程序运行良好并提供预期的输出:"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;
}
Run Code Online (Sandbox Code Playgroud)

for*_*818 5

重要的一点是:

std::string TestShared::getName(void)
{
    return m_name;
}
Run Code Online (Sandbox Code Playgroud)

和这个:

Another an;
an.name = ts->getName().c_str();   // (*)
return an;
Run Code Online (Sandbox Code Playgroud)

getName()返回私有字符串的副本。c_str()返回一个指向该临时的内部字符数组的指针。an.name存储该指针,该指针已经悬空在;in 处(*)

您需要复制字符串,或者char*在您真正需要string.

返回对成员m_namefrom的引用getName()也可以解决当前的问题,但是如果您想an.name存储一个字符串,您实际上应该存储一个字符串,而不仅仅是指向其他字符串的内部缓冲区的指针。

您的代码具有未定义的行为,因为当时您通过printf("Name: %s\n", an.name);指针打印字符串不再有效。将string它指向的是早已不复存在。未定义的行为可能会产生奇怪的效果,例如添加一条看似无关的行来改变行为。当存在额外的代码行时,不要被产生预期输出的代码误导。这只是一个副作用,您的代码是错误的,即使它看起来有效。