C++中unique_ptr<T,D>两种初始化操作的区别及示例
两种
unique_ptr<T,D>构造方式的区别 首先明确两个构造的核心差异在于删除器的来源,同时纠正原书描述里的一处疏漏:unique_ptr<T,D> u2(d)构造出的是空智能指针,并非指向T类型对象(指向对象的构造是unique_ptr<T,D> u2(p, d),其中p是T类型指针)。
1. unique_ptr<T,D> u1:默认构造
- 构造一个空的
unique_ptr(不指向任何对象)。 - 自动使用
D类型的默认构造函数创建一个删除器实例,当这个智能指针后续接管指针(比如通过reset)后,会用这个默认生成的删除器来释放资源。 - 要求
D类型必须支持默认构造(即可以无参创建对象)。
2. unique_ptr<T,D> u2(d):删除器构造
- 同样构造一个空的
unique_ptr。 - 不会默认构造删除器,而是直接使用用户提供的
D类型对象d(会复制或移动d作为自己的删除器)。 - 适用于
D类型无法默认构造的场景,或者需要自定义删除器的初始状态时。
示例代码
场景1:默认构造删除器
#include <memory> #include <iostream> // 可默认构造的自定义删除器 struct LogDeleter { LogDeleter() { std::cout << "LogDeleter: 默认构造实例\n"; } void operator()(int* ptr) { std::cout << "LogDeleter: 释放int指针\n"; delete ptr; } }; int main() { // 默认构造空的unique_ptr,删除器是默认生成的LogDeleter实例 std::unique_ptr<int, LogDeleter> u1; u1.reset(new int(42)); // 接管一个int对象 // 离开作用域时,调用默认构造的LogDeleter释放指针 }
输出:
LogDeleter: 默认构造实例 LogDeleter: 释放int指针
场景2:使用自定义删除器对象
#include <memory> #include <iostream> // 带自定义参数的删除器(无法默认构造) struct TaggedDeleter { int tag; TaggedDeleter(int t) : tag(t) { std::cout << "TaggedDeleter: 构造实例,tag=" << tag << "\n"; } void operator()(int* ptr) { std::cout << "TaggedDeleter: 释放指针,tag=" << tag << "\n"; delete ptr; } }; int main() { // 创建一个自定义参数的删除器对象 TaggedDeleter d(1001); // 用d构造空的unique_ptr,删除器是d的副本 std::unique_ptr<int, TaggedDeleter> u2(d); u2.reset(new int(100)); // 离开作用域时,用tag=1001的删除器释放指针 }
输出:
TaggedDeleter: 构造实例,tag=1001 TaggedDeleter: 释放指针,tag=1001
场景3:默认构造不可行的情况
如果删除器没有默认构造函数,默认构造unique_ptr会编译失败:
struct NoDefaultDeleter { NoDefaultDeleter(int x) {} // 无默认构造函数 void operator()(int* p) { delete p; } }; // 错误:NoDefaultDeleter无法默认构造,u1无法创建 // std::unique_ptr<int, NoDefaultDeleter> u1; // 正确:必须提供现成的删除器对象 NoDefaultDeleter d(5); std::unique_ptr<int, NoDefaultDeleter> u2(d);
内容的提问来源于stack exchange,提问作者gaofeng
相关产品推荐
相关产品推荐

