使用另一个指针对 `unique_ptr` 拥有的对象调用 `delete`
Calling `delete` on an object owned by a `unique_ptr` using another pointer
我有一个指向 class 的指针,由 new
运算符初始化。然后我使用这个指针来设置一个std::unique_ptr
。现在,据我所知,以下代码有双重删除,一次是手动调用 delete
运算符,然后是唯一指针超出范围。此代码如何 运行 "correctly",即没有 运行 时间异常?
#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;
}
输出:
hello world!
In A::A()
In A::printMyStr()
In A::printMyStr()
In A::~A()
In A::~A()
很明显,析构函数 运行s 两次,即使只创建了一个对象。这怎么可能?
注意:我在 64 位上使用 gcc 7.3.0 linux。
双重删除是未定义的行为。
未定义的行为不保证运行时异常;那将被定义。未定义的行为意味着任何事情都可能发生。这可能包括时间旅行、格式化硬盘、通过电子邮件将浏览器历史记录发送给您的联系人,或者什么都不做。
据我所知,我还没有经历过通过电子邮件发送浏览器历史记录。剩下的我都体验过了
如果在 unique_ptr 实例超出范围之前的某个时刻您决定要删除托管对象,只需执行 unique_ptr_instance.reset(nullptr)
。这将调用删除器并导致托管对象变为 nullptr,当实例最终超出范围时删除它是一个空操作。
我有一个指向 class 的指针,由 new
运算符初始化。然后我使用这个指针来设置一个std::unique_ptr
。现在,据我所知,以下代码有双重删除,一次是手动调用 delete
运算符,然后是唯一指针超出范围。此代码如何 运行 "correctly",即没有 运行 时间异常?
#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;
}
输出:
hello world!
In A::A()
In A::printMyStr()
In A::printMyStr()
In A::~A()
In A::~A()
很明显,析构函数 运行s 两次,即使只创建了一个对象。这怎么可能?
注意:我在 64 位上使用 gcc 7.3.0 linux。
双重删除是未定义的行为。
未定义的行为不保证运行时异常;那将被定义。未定义的行为意味着任何事情都可能发生。这可能包括时间旅行、格式化硬盘、通过电子邮件将浏览器历史记录发送给您的联系人,或者什么都不做。
据我所知,我还没有经历过通过电子邮件发送浏览器历史记录。剩下的我都体验过了
如果在 unique_ptr 实例超出范围之前的某个时刻您决定要删除托管对象,只需执行 unique_ptr_instance.reset(nullptr)
。这将调用删除器并导致托管对象变为 nullptr,当实例最终超出范围时删除它是一个空操作。