unique_ptr自定义删除器多场景疑问:为何部分代码报错?
关于std::unique_ptr引用类型删除器的编译问题解析
我正在阅读Nicholai Jossutis所著的STL书籍,书中有一段代码:
D d; // 删除器类型的实例 unique_ptr<int, const D&> p4(new int, D()); // 错误:右值删除器对象 // 无法绑定到引用类型的删除器
对此我无法理解,因此编写了以下测试场景代码:
#include <memory> class C_deleter_functor { public: void operator()(int* iptr) const { delete iptr; } }; class deleter_functor { public: void operator()(int* iptr) { delete iptr; } }; int main() { C_deleter_functor d1; deleter_functor d2; std::unique_ptr<int, const C_deleter_functor&> up1(new int, d1); // 1.OK std::unique_ptr<int, const deleter_functor&> up2(new int, d2); // 2.ERROR std::unique_ptr<int, const C_deleter_functor&> up3(new int, C_deleter_functor{}); // 3.ERROR std::unique_ptr<int, const deleter_functor&> up4(new int, deleter_functor{}); // 4.ERROR }
下面逐个解释每个场景可行或报错的原因:
场景1:up1(编译通过)
- 传入的
d1是左值,可以正常绑定到const C_deleter_functor&类型的引用删除器; C_deleter_functor的operator()是const成员函数,与引用类型的const限定完全匹配,后续调用删除器时不会有访问权限问题。
场景2:up2(编译报错)
deleter_functor的operator()是非const成员函数,但我们指定的删除器类型是const deleter_functor&——通过const引用调用非const成员函数违反了C++的const权限规则,编译器会直接报错。
场景3:up3(编译报错)
- 这里传入的是临时对象
C_deleter_functor{}(右值),虽然const T&语法上可以绑定右值,但std::unique_ptr对于引用类型的删除器有特殊要求:它不会接管右值删除器的生命周期。临时对象在当前语句执行结束后就会被销毁,后续unique_ptr调用删除器时会引用到已销毁的对象,属于未定义行为。因此标准直接禁止这种写法,编译器会报错。
场景4:up4(编译报错)
- 同时存在场景2和场景3的两个问题:
- 传入的是临时右值,不符合引用类型删除器必须绑定左值的要求;
deleter_functor的operator()是非const成员,无法通过const deleter_functor&调用。
内容的提问来源于stack exchange,提问作者rand_program
相关产品推荐
相关产品推荐

