[回答 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页,PDF第585页
如果我理解正确的话,这意味着一个shared_ptr对象从unique_ptr的指针和删除器中构造自身。此外,根据原始问题的答案,我了解到unique_ptr的::pointer类型是T*,应该可以转换为shared_ptr::pointer的T*。因此,删除器应该直接从unique_ptr对象中复制,对吗?template shared_ptr(unique_ptr&& r);
备注:除非unique_ptr :: pointer可转换为T *,否则此构造函数不参与重载决议。
效果:当D不是引用类型时,等效于shared_ptr(r.release(),r.get_deleter()),否则等效于shared_ptr(r.release(),ref(r.get_deleter()))。
异常安全性:如果抛出异常,则构造函数无效。
我做的测试只是因为它实际上与 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的shared array并且希望避免在我的代码中包含
vector
或array
头文件时,该怎么办?
unique_ptr<Derived[]>
转换为shared_ptr<Derived>
->shared_ptr<Base>
时存在潜在的安全问题,请参阅http://stackoverflow.com/q/32483375/981959。 - Jonathan Wakely