[追问this问题]
我最近对c风格数组的智能指针进行了一些处理。我最终做了推荐的事情,并使用智能指针代替向量,但在此期间,我得到了一些建议:不要使用shared_ptr<T>
对象来管理最初用{{1}创建的数组因为它不会调用make_unique<T[]>
而是调用delete[]
。
这对我来说似乎不合逻辑,我检查了Coliru和标准:
此代码:
delete
生成此输出:
#include <iostream>
#include <memory>
int main()
{
std::cout << "start!\n";
auto customArrayAllocator = [](unsigned int num){
std::cout << "custom array allocator\n";
return new int[num];
};
std::cout << "allocator constructed\n";
auto customArrayDeleter = [](int *ptr){
std::cout << "custom array deleter\n";
delete[] ptr;
};
std::cout << "deleter constructed\n";
std::unique_ptr<int[], decltype(customArrayDeleter)>
myUnique(customArrayAllocator(4), customArrayDeleter);
std::cout << "unique_ptr constructed\n";
std::shared_ptr<int>
myShared = std::move(myUnique);
std::cout << "shared_ptr constructed\n";
}
这似乎表明start!
allocator constructed
deleter constructed
custom array allocator
unique_ptr constructed
shared_ptr constructed
custom array deleter
的删除符会像我预期的那样传递给unique_ptr<T[]>
。
来自C ++ 14标准§20.8.2.2.1pg. 571 of doc, 585 of pdf
模板shared_ptr(unique_ptr&amp;&amp; r);
备注:除非unique_ptr :: pointer,否则此构造函数不应参与重载决策 可转换为T *。
效果:当D不是引用类型时,等效于shared_ptr(r.release(),r.get_deleter()) 否则shared_ptr(r.release(),ref(r.get_deleter())) 异常安全性:如果抛出异常,则构造函数无效。
如果我正确阅读,则意味着shared_ptr<T>
对象从shared_ptr
的指针和删除器构造自身。此外,我的理解(从原始问题的答案)unique_ptr
类型的::pointer
是unique_ptr<T[]>
,它应该可以转换为T*
的{{1} }}。所以删除器应该直接从shared_ptr<T>::pointer
对象复制,对吧?
我的测试是否有效,因为它实际上并不等同于T*
的功能,或者是语法
unique_ptr
的良好,异常安全(和清洁)替代方案
std::make_shared<T[]>
之类的,当我无法使用Boost的shared array并希望避免在我的代码中包含std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);
或std::shared_ptr<T> mysharedArray(new T[16], [](T* ptr){delete[] ptr;});
标题时?
答案 0 :(得分:6)
是的,您的例子有效,原因就在于您所说的理由。 unique_ptr::pointer
为int *
,您试图将其所有权转移给shared_ptr<int>
,因此您列出的转换构造函数将参与重载解析,并且制作删除者(std::default_delete<int[]>
)的副本,因为它不是引用类型。
以下内容有效,并在delete[]
引用计数为零时调用shared_ptr
std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);
除了你所展示的lambda之外,写这个的另一种方法是
std::shared_ptr<T> mySharedArray(new T[16], std::default_delete<int[]>());
将导致mySharedArray
获取与上一行相同的删除器。