[英]Initialization of shared_ptr<T> from unique_ptr<T[]>
[Followup to this question] [跟进这个问题]
I've been dealing a little bit with smart pointers to c-style arrays recently. 最近,我一直在处理一些关于c风格数组的智能指针。 I ultimately wound up doing the recommended thing and using smart pointers to vectors instead, but during that period, I got a bit of advice: don't use a
shared_ptr<T>
object to manage an array initially made with make_unique<T[]>
because it won't call delete[]
but rather delete
. 我最终做了推荐的事情,并使用智能指针代替向量,但在此期间,我得到了一些建议:不要使用
shared_ptr<T>
对象来管理最初使用make_unique<T[]>
的数组make_unique<T[]>
因为它不会调用delete[]
而是delete
。
This didn't seem logical to me, and I checked both Coliru and the Standard: 这对我来说似乎不合逻辑,我检查了Coliru和标准:
This code: 这段代码:
#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";
}
produces this output: 产生这个输出:
start!
allocator constructed
deleter constructed
custom array allocator
unique_ptr constructed
shared_ptr constructed
custom array deleter
Which seems to indicate that the unique_ptr<T[]>
's deleter is passed to the shared_ptr<T>
, as I expected. 这似乎表明
unique_ptr<T[]>
的删除器被传递给shared_ptr<T>
,正如我预期的那样。
From the C++14 Standard § 20.8.2.2.1 pg. 来自C ++ 14标准§20.8.2.2.1pg 。 571 of doc, 585 of pdf
doc的571,pdf的585
template shared_ptr(unique_ptr&& r);
template shared_ptr(unique_ptr && r);
Remark : This constructor shall not participate in overload resolution unless unique_ptr::pointer is convertible to T*.备注 :除非unique_ptr :: pointer可转换为T *,否则此构造函数不应参与重载决策。
Effects : Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type, otherwise shared_ptr(r.release(), ref(r.get_deleter())).效果 :当D不是引用类型时,等效于shared_ptr(r.release(),r.get_deleter()),否则为shared_ptr(r.release(),ref(r.get_deleter()))。
Exception safety : If an exception is thrown, the constructor has no effect.异常安全 :如果抛出异常,则构造函数无效。
If I'm reading that right, it means that a shared_ptr
object constructs itself from both the pointer and the deleter of a unique_ptr
. 如果我正确读取它,则意味着
shared_ptr
对象从unique_ptr
的指针和删除器构造自身。 Furthermore, it's my understanding (from the answer to the original question) that the ::pointer
type of unique_ptr<T[]>
is T*
, which should be convertible to shared_ptr<T>::pointer
's T*
. 此外,我的理解(从原始问题的答案),
unique_ptr<T[]>
的::pointer
类型是T*
,它应该可以转换为shared_ptr<T>::pointer
的T*
。 So the deleter should just be copied right from the unique_ptr
object, right? 所以删除器应该直接从
unique_ptr
对象复制,对吧?
Did my test only work because it's not actually equivalent to the function of std::make_shared<T[]>
, or is the syntax 我的测试是否有效,因为它实际上并不等同于
std::make_shared<T[]>
,或者是语法
std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);
a good, exception safe (and cleaner) alternative to 一个好的,异常安全(和更清洁)的替代品
std::shared_ptr<T> mysharedArray(new T[16], [](T* ptr){delete[] ptr;});
and its ilk, when I am unable to use Boost's shared array and desire to avoid including either the vector
or the array
header with my code? 当我无法使用Boost的共享数组并且希望避免在我的代码中包含
vector
或array
头时,它的同类?
Yes, your example is valid for the very reasons you've stated. 是的,你的例子是有效的,因为你说的原因。
unique_ptr::pointer
is int *
, and you're trying to pass ownership of that to a shared_ptr<int>
, so the converting constructor you've listed will participate in overload resolution, and will make a copy of the deleter ( std::default_delete<int[]>
) because it's not a reference type. unique_ptr::pointer
是int *
,你试图将它的所有权传递给shared_ptr<int>
,所以你列出的转换构造函数将参与重载解析,并将复制删除器( std::default_delete<int[]>
)因为它不是引用类型。
So the following is valid, and will call delete[]
when the shared_ptr
reference count goes to zero 因此以下是有效的,并且当
shared_ptr
引用计数变为零时将调用delete[]
std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);
Another way to write this, other than the lambda you've shown, is 除了你展示的lambda之外,另一种写这个的方法是
std::shared_ptr<T> mySharedArray(new T[16], std::default_delete<int[]>());
which will result in mySharedArray
acquiring the same deleter as the previous line. 这将导致
mySharedArray
获取与前一行相同的删除器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.