我遇到了一个令我困惑的问题。这与我是选择存储对象还是指向它的指针有关。
这是我的班级:
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;
}
答案 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:当对象被销毁时,其所有成员也被销毁(就调用他们的析构函数而言)。由于x
是int
,因此它在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;
临时对象将处于活动状态,而引用将处于活动状态。