为什么在自定义删除器的unique_ptr中,即使对象为nullptr,其删除操作仍会引发未定义行为,而shared_ptr却能优雅地处理?

2026-04-16 19:353阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计513个文字,预计阅读时间需要3分钟。

为什么在自定义删除器的unique_ptr中,即使对象为nullptr,其删除操作仍会引发未定义行为,而shared_ptr却能优雅地处理?

使用 `unique_ptr` 或 `shared_ptr` 作为资源管理的简单代码如下:

cpp#include

int main() { std::unique_ptr uptr(new int(10)); // 使用 unique_ptr 管理动态分配的内存 // 使用 uptr... uptr.reset(); // 释放资源,自动删除内部指针指向的对象 return 0;}

请注意,此代码使用 `unique_ptr` 来管理动态分配的内存。当 `unique_ptr` 对象超出作用域或被重置时,它会自动删除其内部指针指向的对象。这样做可以避免内存泄漏。在 Visual C++ 2017 (14.1) 中,`unique_ptr` 的行为与 C++ 标准库中的定义一致。

使用unique_ptr或shared_ptr作为范围保护的简单代码.有关清除内容的所有信息都在删除器中捕获,因此我尽管将nullptr用于构造函数是安全的.

显然,使用Visual C 2017(14.1),它不能像unique_ptr那样工作,但适用于shared_ptr.这是微软的怪癖,还是标准阻止在持有nullptr时调用unique_ptr的删除?

在下面的代码中,我被迫用(void *)1构造一个unique_ptr.如果我使用nullptr构造它,则不会调用cleaner.对于shared_ptr,没有区别,总是调用清理器.

#include <memory> #include <iostream> int main() { int ttt = 77; auto cleaner = [&ttt](void*) { std::cout << "cleaner: " << ttt << "\n"; // do something with capture here instead of print }; std::unique_ptr<void, decltype(cleaner)> p((void*)1, cleaner); std::shared_ptr<void> q(nullptr, [&ttt](void*) { std::cout << "shared: " << ttt << "\n"; // do something with capture here instead of print }); std::cout << "done\n"; return 0; } unique_ptr的析构函数需要这样做:

23.11.1.2.2 unique_ptr destructor [unique.ptr.single.dtor]

2 Effects: If get() == nullptr there are no effects. Otherwise get_deleter()(get()).

实际上shared_ptr的析构函数需要执行相同的操作:

23.11.2.2.2 shared_ptr destructor [util.smartptr.shared.dest]

为什么在自定义删除器的unique_ptr中,即使对象为nullptr,其删除操作仍会引发未定义行为,而shared_ptr却能优雅地处理?

— (1.1) If *this is empty or shares ownership with another shared_ptr instance ( use_count() > 1 ), there are no side effects.

— (1.2) Otherwise, if *this owns an object p and a deleter d, d(p) is called.

所以依靠智能指针在传递空指针时在范围出口执行任意操作是不可靠的.

标签:uniqueptr

本文共计513个文字,预计阅读时间需要3分钟。

为什么在自定义删除器的unique_ptr中,即使对象为nullptr,其删除操作仍会引发未定义行为,而shared_ptr却能优雅地处理?

使用 `unique_ptr` 或 `shared_ptr` 作为资源管理的简单代码如下:

cpp#include

int main() { std::unique_ptr uptr(new int(10)); // 使用 unique_ptr 管理动态分配的内存 // 使用 uptr... uptr.reset(); // 释放资源,自动删除内部指针指向的对象 return 0;}

请注意,此代码使用 `unique_ptr` 来管理动态分配的内存。当 `unique_ptr` 对象超出作用域或被重置时,它会自动删除其内部指针指向的对象。这样做可以避免内存泄漏。在 Visual C++ 2017 (14.1) 中,`unique_ptr` 的行为与 C++ 标准库中的定义一致。

使用unique_ptr或shared_ptr作为范围保护的简单代码.有关清除内容的所有信息都在删除器中捕获,因此我尽管将nullptr用于构造函数是安全的.

显然,使用Visual C 2017(14.1),它不能像unique_ptr那样工作,但适用于shared_ptr.这是微软的怪癖,还是标准阻止在持有nullptr时调用unique_ptr的删除?

在下面的代码中,我被迫用(void *)1构造一个unique_ptr.如果我使用nullptr构造它,则不会调用cleaner.对于shared_ptr,没有区别,总是调用清理器.

#include <memory> #include <iostream> int main() { int ttt = 77; auto cleaner = [&ttt](void*) { std::cout << "cleaner: " << ttt << "\n"; // do something with capture here instead of print }; std::unique_ptr<void, decltype(cleaner)> p((void*)1, cleaner); std::shared_ptr<void> q(nullptr, [&ttt](void*) { std::cout << "shared: " << ttt << "\n"; // do something with capture here instead of print }); std::cout << "done\n"; return 0; } unique_ptr的析构函数需要这样做:

23.11.1.2.2 unique_ptr destructor [unique.ptr.single.dtor]

2 Effects: If get() == nullptr there are no effects. Otherwise get_deleter()(get()).

实际上shared_ptr的析构函数需要执行相同的操作:

23.11.2.2.2 shared_ptr destructor [util.smartptr.shared.dest]

为什么在自定义删除器的unique_ptr中,即使对象为nullptr,其删除操作仍会引发未定义行为,而shared_ptr却能优雅地处理?

— (1.1) If *this is empty or shares ownership with another shared_ptr instance ( use_count() > 1 ), there are no side effects.

— (1.2) Otherwise, if *this owns an object p and a deleter d, d(p) is called.

所以依靠智能指针在传递空指针时在范围出口执行任意操作是不可靠的.

标签:uniqueptr