C++ 使用另一个指针对“unique_ptr”拥有的对象调用“delete”
我有一个指向由C++ 使用另一个指针对“unique_ptr”拥有的对象调用“delete”,c++,c++11,smart-pointers,unique-ptr,delete-operator,C++,C++11,Smart Pointers,Unique Ptr,Delete Operator,我有一个指向由new操作符初始化的类的指针。然后我使用这个指针设置一个std::unique\u ptr。现在,据我所知,下面的代码有双重删除,一次手动调用delete操作符,然后当唯一指针超出范围时。该代码如何“正确”运行,即没有运行时异常 #include <iostream> #include <memory> class A { public: A() { std::cout<<"In A::A()\n"; }
new
操作符初始化的类的指针。然后我使用这个指针设置一个std::unique\u ptr
。现在,据我所知,下面的代码有双重删除,一次手动调用delete
操作符,然后当唯一指针超出范围时。该代码如何“正确”运行,即没有运行时异常
#include <iostream>
#include <memory>
class A
{
public:
A()
{
std::cout<<"In A::A()\n";
}
~A()
{
std::cout<<"In A::~A()\n";
}
void printMyStr()
{
std::cout<<"In A::printMyStr()\n";
}
};
int main()
{
std::cout<<"hello world!\n";
A * pa = new A();
std::unique_ptr<A> upa(pa);
pa->printMyStr();
upa->printMyStr();
delete pa; // How does this not create problems?
return 0;
}
显然,析构函数运行两次,即使只创建了一个对象。这怎么可能
注意:我在64位linux上使用gcc 7.3.0。双重删除是未定义的行为 未定义的行为不能保证运行时异常;这将被定义。未定义的行为意味着任何事情都可能发生。这可能包括时间旅行、格式化硬盘、通过电子邮件向联系人发送浏览器历史记录,或者什么都不做
据我所知,我还没有体验过通过电子邮件发送浏览器历史记录。我已经经历了剩下的。双重删除是未定义的行为 未定义的行为不能保证运行时异常;这将被定义。未定义的行为意味着任何事情都可能发生。这可能包括时间旅行、格式化硬盘、通过电子邮件向联系人发送浏览器历史记录,或者什么都不做
据我所知,我还没有体验过通过电子邮件发送浏览器历史记录。我已经经历了其余的过程。如果在唯一\u ptr实例超出范围之前的某个时间点,您决定删除托管对象,只需执行
unique\u ptr\u instance.reset(nullptr)
。这将调用删除程序并导致托管对象变为nullptr,当实例最终超出范围时删除该对象是不可操作的。如果在unique_ptr实例超出范围之前的某个时刻,您决定删除托管对象,只需执行unique_ptr_instance.reset(nullptr)
。这将调用deleter并导致托管对象变为null ptr,当实例最终超出范围时删除该对象是不可操作的。这只是未定义的行为,而不是会引发异常的行为。如果您通过valgrind运行它,它应该会告诉您有一个问题。“这怎么可能?”对于未定义的行为,任何事情都是可能的。(包括“看起来正常工作”。)这只是未定义的行为,而不是引发异常的行为。如果您通过valgrind运行它,它应该会告诉您有一个问题。“这怎么可能?”对于未定义的行为,任何事情都是可能的。(包括“看起来工作正常”。)你真的体验过硬盘的格式化吗?@einpoklum我经历过文件系统因UB而损坏,尽管没有重新格式化。但没有理由不这样做。另一方面,“时间旅行”…@einpok是内存损坏,将错误的(垃圾)参数传递给(相当可怕的)文件系统API,清除HDD的格式,如果我没记错的话。但是是的,这是一个bug(与UB一起),其症状是“HDD丢失格式”。@Yakk AdamNevraumont:但这是一种欺骗。我的意思是,文件系统API的定义行为可能涉及删除内容。有一个2017年CppCon的演讲,Piotr Padlewski在会上解释了如何在不经意和意外的情况下实现这一点。@einp我不记得API到底是什么。可能是试图“创建临时文件”之类的。销毁驱动器不是function应该能够做的事情之一。我相信那是DOS时代,用户空间可以完全访问硬盘硬件。你真的体验过硬盘的格式化吗?@einpoklum我经历过UB导致的文件系统损坏,尽管没有重新格式化。但没有理由不这样做。另一方面,“时间旅行”…@einpok是内存损坏,将错误的(垃圾)参数传递给(相当可怕的)文件系统API,清除HDD的格式,如果我没记错的话。但是是的,这是一个bug(与UB一起),其症状是“HDD丢失格式”。@Yakk AdamNevraumont:但这是一种欺骗。我的意思是,文件系统API的定义行为可能涉及删除内容。有一个2017年CppCon的演讲,Piotr Padlewski在会上解释了如何在不经意和意外的情况下实现这一点。@einp我不记得API到底是什么。可能是试图“创建临时文件”之类的。销毁驱动器不是function应该能够做的事情之一。我相信那是DOS时代,用户空间可以完全访问硬盘。
hello world!
In A::A()
In A::printMyStr()
In A::printMyStr()
In A::~A()
In A::~A()