[此问题的跟进]
最近,我一直在处理指向c样式数组的智能指针。最终,我做了最后的建议,而是使用了智能的指向矢量的指针,但是在此期间,我得到了一些建议:不要使用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[]>
的Deleter已传递给shared_ptr<T>
。
从C ++ 14标准§20.8.2.2.1 pg。doc 571,pdf 585
模板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()))。
异常安全性:如果引发异常,则构造方法无效。
如果我没看错,那意味着shared_ptr
对象从的指针和删除器构造自己unique_ptr
。此外,根据我的理解(从对原始问题的回答),is的::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的共享数组并希望避免vector
在array
代码中包含或标头时?
是的,由于您陈述的原因,您的示例是有效的。unique_ptr::pointer
是int *
,并且您正尝试将其所有权传递给shared_ptr<int>
,因此您列出的转换构造函数将参与重载解析,并且将复制deleter(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
获得与上一行相同的删除器。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句