[后续this问题]
最近我一直在处理一些指向 C 风格数组的智能指针。我最终做了推荐的事情并使用指向向量的智能指针代替,但在那段时间,我得到了一些建议:不要使用shared_ptr<T>
管理最初使用的数组的对象make_unique<T[]>
因为它不会打电话delete[]
反而delete
.
这对我来说似乎不合逻辑,我检查了两者Coliru和标准:
这段代码:
#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[]>
的删除器被传递给shared_ptr<T>
,正如我所料。
来自 C++14 标准 § 20.8.2.2.1第 页571 文档,585 pdf
模板shared_ptr(unique_ptr&& r);
Remark:此构造函数不应参与重载决策,除非 unique_ptr::pointer
可转换为 T*。
Effects:当D不是引用类型时,相当于shared_ptr(r.release(), r.get_deleter()),
否则shared_ptr(r.release(), ref(r.get_deleter()))。
异常安全:如果抛出异常,构造函数没有任何作用。
如果我没理解错的话,这意味着shared_ptr
对象从指针和删除器构造自身unique_ptr
。此外,据我了解(根据原始问题的答案)::pointer
类型unique_ptr<T[]>
is T*
,这应该可以转换为shared_ptr<T>::pointer
's T*
。所以删除器应该直接从unique_ptr
对象,对吗?
我的测试之所以有效,是因为它实际上并不等同于std::make_shared<T[]>
,或者是语法
std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);
一个良好的、异常安全(且更清洁)的替代品
std::shared_ptr<T> mysharedArray(new T[16], [](T* ptr){delete[] ptr;});
等等,当我无法使用 Boost 时共享数组并希望避免包括vector
or the array
标题与我的代码?