string在构造函数中分配,但在C ++之后变为空白

时间:2015-07-10 18:52:52

标签: c++ pointers constructor

我遇到了一个令我困惑的问题。这与我是选择存储对象还是指向它的指针有关。

这是我的班级:

class Test {
public:
    std::string abc;
    int x;

    Test(std::string def, int y) {
        abc = def;
        cout << abc << endl; //THIS ALWAYS GIVES "ghi"
        x = y;
    }
};

将其存储为指针:

    Test* T1 = &Test{ "ghi", 100 };
    cout << T1->abc << endl; //**THIS IS BLANK -- WHY!?**
    cout << T1->x << endl; //THIS GIVES 100

将其存储为对象本身:

    Test T2 = Test{ "ghi", 100 };
    cout << T2.abc << endl; //THIS GIVES "ghi"
    cout << T2.x << endl; //THIS GIVES 100

我对C ++比较陌生,但根据我的理解,T1-&gt; abc应该取消引用指针T1(因此我有一个Test对象),然后访问该Test对象的成员abc。由于我已经创建了对象,因此它应该是&#34; ghi&#34;。但这给了空白。

显然,这仅适用于字符串成员而不适用于整数成员,因为T1-&gt; x工作正常。

当我存储对象而不是指向它的指针时,问题并不存在,如对象T2所示。

我已经检查过,在构建T1和T2期间,abc始终是&#34; ghi&#34; 里面构造函数。不知何故,在构造之后,字符串就会消失。

另外,根据我读到的内容,abc = def复制字符串内容而不是指针,因此它可能不是范围问题。

https://msdn.microsoft.com/en-us/library/b930c881.aspx非常清楚地表明在任何一种情况下,是否 - &gt;要么 。使用,可以进行分配。

搜索Google和stackoverflow没有帮助。因此,你的赞赏。提前谢谢。

class Test {
public:
    std::string abc;
    int x;

    Test(std::string def, int y) {
        abc = def;
        x = y;
    }
};

int main() {

    Test* T1 = &Test{ "ghi", 100 };
    cout << T1->abc << endl; //THIS IS BLANK -- WHY!?
    cout << T1->x << endl; //THIS GIVES 100

    Test T2 = Test{ "ghi", 100 };
    cout << T2.abc << endl; //THIS GIVES "ghi"
    cout << T2.x << endl; //THIS GIVES 100

    return 0;
}

4 个答案:

答案 0 :(得分:2)

这个结构:

Test{ "ghi", 100 };

创建您要指向的临时变量。这是错的。

如果您想使用指针存储它:

Test* T1 = new Test{ "ghi", 100 };

cout << T1->abc << endl; //This is not blank anymore
cout << T1->x << endl;

delete T1; //Do NOT forget this!

顺便说一句,如果你想知道,为什么这一行:

cout << T1->x << endl;

仍在评估为100:当对象被销毁时,其所有成员也被销毁(就调用他们的析构函数而言)。由于xint,因此它在no-op中的析构函数和由它占用的内存内容不会改变。

另一方面,abc是和std::string,它在销毁期间释放了已分配的内存 - 因此T1->abc指的是一个空字符串。

答案 1 :(得分:1)

Test* T1 = &Test{ "ghi", 100 };

请不要这样做。这正是造成问题的原因。而是使用

Test* T1 = new Test("ghi", 100);

因为第一种方法创建了对临时对象的引用,在您尝试获取打印字符串之前该临时对象会消失。

它适用于非指针,因为您将临时对象提供给新对象。

不记得删除(因为你使用了新的)

delete T1;

或者,正如πάνταῥεῖ所指出的那样,更安全,更好的c ++编码实践,就是使用smart pointer。想到的最相关的是unique_ptr。

std::unique_ptr<Test> T1(new Test());
std::cout << T1->abc << std::endl;
...

答案 2 :(得分:1)

  Test* T1 = &Test{ "ghi", 100 };

Test{ "ghi", 100 }的临时 rvalue 会立即超出范围,并在此声明后不再存在。

因此将其解除引用

 cout << T1->abc << endl;

只需在悬空指针上调用 Undefned Behavior

答案 3 :(得分:1)

此代码段

Test* T1 = &Test{ "ghi", 100 };
cout << T1->abc << endl; //**THIS IS BLANK -- WHY!?**
cout << T1->x << endl; //THIS GIVES 100

具有未定义的行为,因为在语句

之后
Test* T1 = &Test{ "ghi", 100 };

临时对象Test {“ghi”,100}将被删除,指针变为无效。

有效代码可以采用以下方式

Test* T1 = new Test{ "ghi", 100 };

cout << T1->abc << endl;
cout << T1->x << endl; 

delete T1;

或者您可以使用对临时对象的常量引用来代替指针。例如

const Test &T1 = Test{ "ghi", 100 };

cout << T1.abc << endl;
cout << T1.x << endl; 

临时对象将处于活动状态,而引用将处于活动状态。