为什么 std::shared_ptr = std::unique_ptr<T[]> 编译,而 std::shared_ptr<T[]><T> = std::uni
Why does std::shared_ptr<T> = std::unique_ptr<T[]> compile, while std::shared_ptr<T[]> = std::unique_ptr<T[]> does not?
我在 Coliru 中使用以下输入命令探讨了这个主题:
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
测试可以在这里找到,但我在下面发布了代码。我在示例中使用了int
,因为它是基本类型。
#include <iostream>
#include <memory>
struct Foo{
Foo() :
a_{0}, b_{1}, c_{-1}, combination_{0.5} {}
int
a_,
b_,
c_;
double
combination_;
};
int main()
{
//int
// *unManagedArray = new int[16];
std::unique_ptr<int[]>
uniqueArrayOrigin = std::make_unique<int[]>(16);
std::shared_ptr<int>
// works but needs call to new
// sharedSingleTest{unManagedArray, std::default_delete<int[]>{}};
// works, does not require call to new
sharedSingleUnique = std::make_unique<int[]>(16);
// compilation error (conversion to non-scalar type)
// sharedSingleDerived = uniqueArrayOrigin;
// std::shared_ptr<int[]>
// compilation errors
// sharedArrayTest{unManagedArray, std::default_delete<int[]>{}};
// compilation error (conversion to non-scalar type)
// sharedArrayUnique = std::make_unique<int[]>(16);
// compilation error (conversion to non-scalar type)
// sharedArrayDerived = uniqueArrayOrigin;
std::shared_ptr<Foo>
// works: specified overload of operator= for shared_ptr
nonArrayTest = std::make_unique<Foo>();
std::cout << "done!n";
}
我在SO上寻找答案,但只提到了没有专业化std::shared_ptr
的实施,这主要是因为没有人费心向标准委员会提出关于这个主题的适当建议。
我很好奇,因为我会在 cpp偏好std::shared_ptr<T[]>.operator=(std::unique_ptr<T[], Deleter>&&)
解释operator=
的第 4 次重载,以表明这种语法是合法的——毕竟,无论std::shared_ptr
数组类型的专用状态如何,T[]
和T[]
都是相同的类型。
此外,这种语法似乎只适用于std::make_unique<T[]>
的乘积,而不是唯一的指针对象,这与我对主题的理解背道而驰——调用不应该是有效的相同,尽管一个移动一个现有对象,另一个,嗯,移动一个刚刚创建的对象?我希望它们之间的唯一区别是在第一种情况下函数调用后的无效std::unique_ptr<T[]>
。
作为旁注,我假设由于有一种方法可以将动态分配的数组构造到不需要使用new
的shared_ptr
中,我应该更喜欢它而不是更混乱和异常不安全的调用new T[N]
?
tl;博士:
operator=
在std::shared_ptr<T[]>
和std::unique_ptr<T[]>
之间根本不起作用,尽管我希望它能工作。为什么?- 如果有的话,我希望从
T[]
到T
的类型转换是唯一指针和共享指针之间编译错误的根源。为什么会这样? operator=
在std::shared_ptr<T>
和std::make_unique<T[]>
之间工作,但不是std::unique_ptr<T[]>
。为什么?
在- 需要动态分配的共享数组的情况下,我假设是否正确,但是在我不想使用boost或向量的情况下(原因如下),我应该调用
operator= std::make_unique<T[]>(N)
?
为什么我不使用?
- Boost:尚未批准在我的公司使用,我不知道何时或是否会获得使用它的批准。
- 数组:我必须在运行时确定此数组的大小。
- 向量:我正在研究一个实时信号处理系统,并且希望避免额外的指针取消引用。我还试图避免在我的头文件中包含无关的库(这是为了读取和写入子系统之间的通信)但是,如果它很重要(过早优化......)并咬紧牙关,我最终选择稍后对其进行优化。不过,问题仍然存在。
§20.8.2.2.1/28:
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
备注:此构造函数不得参与重载解析 除非
unique_ptr<Y, D>::pointer
可转换为T*
.
然而,unique_ptr<U[]>::pointer
实际上是U*
,而shared_ptr<U[]>
的T*
是U(*)[]
;并且U*
不能转换为U(*)[]
,因此从不考虑过载。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用std::vector的OpenCL矩阵乘法
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::condition_variable::wait()如何评估给定的谓词
- 如何获取std::result_of函数的返回类型
- std::原子加载和存储都需要吗
- 将对象移动到std::shared_ptr
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 是std :: set&lt; std :: future&gt;不可能存在
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- 使用 std::vector<boost::shared_ptr<Base_Class>> 或 boost::p tr_vector 的性能注意事项是什么<Base>
- std::map<std::set, double> AND std:<long>map< std::p air<long, long>, double>
- 如何获取std::vector<DMatch>