[this问题的跟进]
最近,我一直在处理指向c样式数组的智能指针。我最终做了最后的建议,而是使用智能指针指向 vector ,但是在此期间,我得到了一些建议:不要使用shared_ptr<T>
对象来管理最初由make_unique<T[]>
构成的数组,因为它不会调用delete[]
而是delete
。
这对我来说似乎不合逻辑,我同时检查了Coliru和Standard:
这段代码:
#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 pg. 571 of doc, 585 of pdf
如果我没看错,那意味着
shared_ptr
对象从unique_ptr
的指针和删除器构造自己。此外,根据我对原始问题的回答,我的理解是::pointer
的unique_ptr<T[]>
类型为T*
,应将其转换为shared_ptr<T>::pointer
的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的shared array并希望避免在我的代码中包含
vector
或array
header 时? 最佳答案
是的,由于您陈述的原因,您的示例是有效的。 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
获取与上一行相同的删除器。关于c++ - 从unique_ptr <T []>初始化shared_ptr <T>,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30495941/