std::shared_ptr 和 std::unique_ptr 构造函数之间的不对称
assymetry between std::shared_ptr and std::unique_ptr constructors
在C++03期间,我们没有unique_ptr
,所以我改用了tr1::shared_ptr
。
现在,在 C++11 中,在这种情况下,我将替换如下调用:
tr1::shared_ptr<X> o(new X);
跟
std::unique_ptr<X> o(new X);
不幸的是,由于某种原因,我无法替换包含删除器的情况,其中删除器是一个函数:
void special_delete(Y *p) { ... }
tr1::shared_ptr<Y> o(new Y(), special_delete);
std::unique_ptr<Y> o(new Y(), special_delete); // does not compile
std::unique_ptr<Y, std::function<void(Y*)> > o(new Y(), special_delete); // this compiles
为什么会这样? 有没有一种同构的方法可以用unique_ptr构造函数替换所有shared_ptr构造函数?
我已经创建了这个,但我对此并不满意。
template <class Y>
using unique_ptr_with_deleter = std::unique_ptr<Y, std::function<void(Y*)> >;
unique_ptr_with_deleter<Y> o(new Y(), special_delete); // this compiles
shared_ptr
模板类型擦除删除程序。对于您想要的任何类型的删除程序,只有一种类型的shared_ptr<T>
。这是一个非常重量级(且昂贵(的工具。
相比之下,unique_ptr
使删除程序成为类型的一部分,因此它没有动态调用开销。unique_ptr<T, D>
几乎和原始指针一样便宜。
请注意,您可以从任何删除程序类型的unique_ptr<T, D>
右值构造shared_ptr<T>
D
。
对您的解决方案的随机评论:这两种解决方案都不是很好。使用函数指针作为删除器不必要地使删除器成为unique_ptr状态的动态部分。std::function
情况更糟,使用整个类型擦除虚拟调度机制进行删除 - 请记住,您静态知道如何删除!
更好的解决方案是通过编写自己的类型使删除器成为类型的一部分,而不是值的一部分:
struct YDeleter { void operator()(Y* p) { special_delete(p); } };
std::unique_ptr<Y, YDeleter> p(new Y); // or presumaby some special factory
这样,整个删除逻辑在编译时是已知的,并且可以尽可能多地内联,而无需额外的函数调用间接寻址。
您应该提供删除器类型
std::unique_ptr<Y, decltype(&special_delete)> o{new Y{}, &special_delete};
请注意,用std::unique_ptr<X> o(new X);
替换tr1::shared_ptr<X> o(new X);
不是一个好主意,通常不应该工作。std::unique_ptr
更像是auto_ptr
的替代品。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- 引用 std::shared:ptr 以避免引用计数
- C++14 unique_ptr并使用已删除的函数'std::unique-ptr' unique_ptr错误
- 使用std :: String ptr的错误打印std :: String
- C++中的大小释放:全局运算符delete的正确行为是什么(void*ptr,std::size_t size)
- std::哈希表示无序映射中的唯一 PTR
- boost::shared_ptr和std::shared-ptr的同居
- 我可以用std::shared_ptr而不是boost::shared-ptr构建boost库吗
- 正确使用std智能指针以确保ptr安全
- 如何创建 std::string 包装器,它将 ptr 保留为 std::string 和 ptr 到创建该包装器实例的
- 为什么 std::string{ "const char ptr" } 有效?
- 为什么 gcc 4.9.0 中没有定义"void operator delete(void* ptr, std::size_t size) noexcept;"?
- 在 std::map 的值中使用非 ptr 是一种很好的做法吗
- 共享 PTR - C++:std::shared_ptr<T> 和 std::shared_ptr<T const> 有什么区别?