删除两次内置指针导致未定义,但在这种情况下发生了什么? 在这段代码中,共享指针是未定义的吗?
string *str_1 = new string;
std::shared_ptr<string> str_ptr(str_1);
*str_1 = "C++";
cout << *str_ptr << endl;
*str_ptr = "C#";
cout << *str_1 << endl;
// str_1 & str_ptr refers same piece of memory
delete str_1;
cout << *str_ptr << endl; // Is this undefined?
答案 0 :(得分:3)
您的代码未定义,因为在调用删除原始指针后,shared_ptr
会留下悬空指针引用。然后继续取消引用已释放的内存(未定义的行为1)。当shared_ptr
超出范围时,它将在被告知要管理的指针上调用delete
,这将释放已释放的内存(未定义的行为2)。
为方便起见,shared_ptr
允许从原始指针初始化,但您应该允许它之后管理分配的内存。当您将原始指针赋予shared_ptr
时,管理原始指针(例如,删除它或初始化另一个shared_ptr
)是错误的。
使用shared_ptr
使用辅助函数make_shared
时,实际上这是更好的做法。
std::shared_ptr<std::string> sp = std::make_shared<std::string>("C++");
此格式避免了您必须处理创建原始指针。事实证明它更有效,因为它避免了智能指针在传递原始指针时必须进行的额外分配。
答案 1 :(得分:2)
sharped_ptr
不是魔法。一旦对象的最后delete
被销毁,它就会调用shared_ptr
。因此,代码调用delete
两次,一次删除str_1
,然后str_ptr
超出范围。因此,使用shared_ptr
与显式调用delete
相比没有任何改变:结果是未定义的行为。
shared_ptr
的发明是为了承担你明确的delete
电话的负担。因此,也没有理由将shared_ptr
和显式delete
结合使用。因此,即使它没有导致未定义的行为,我的建议仍然是:不要这样做!