通过共享指针访问类成员

问题描述

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

程序运行良好并给出了预期的输出"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 早已不复存在。未定义的行为可能会产生奇怪的效果,例如添加一条看似无关的行来改变行为。当存在额外的代码行时,不要被产生预期输出的代码误导。这只是一个副作用,您的代码是错误的,即使它看起来有效。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...