多态性unique_ptr复制省略
polymorphic unique_ptr copy elision
我有以下代码适用于 Clang 5.0,但不适用于 Clang 3.8,启用了 C++14:
class Base {};
class Derived : public Base {};
std::unique_ptr<Base> MakeDerived()
{
auto derived = std::make_unique<Derived>();
return derived;
}
int main()
{
auto base = MakeDerived();
std::cout << "Type: " << typeid(base).name() << 'n';
}
现场样品在这里
在这种情况下,由于复制省略,返回值在技术上是否被移动构造?如果是这样,这是否意味着unique_ptr
的移动构造函数旨在支持用户类类型的隐式向上转换?很难从 cppreference 文档 中分辨出来,除非我应该在该文档页面上假设模板类型U
与类本身的类型T
明显不同。
很明显这有效的一件事是unique_ptr
不是可复制可构造的,并且由于我不通过std::move()
将其转换为右值,因此除了复制 elision 之外,没有其他解释可以解释为什么代码会编译。但是,因为它不适用于接受-std=c++14
标志的 clang 3.8,我想确保标准本身保证在某个地方(如果是这样,在哪里),这只是编译器错误或缺乏支持 问题在 Clang 的 v3.8 中。
Copy elision(在 C++17 之前)总是要求 elided 构造函数是实际可访问的,因此它不能成为代码工作的原因。
但是请注意,C++(自 C++11 起)有一条规则 (12.8/32),该规则归结为以下内容:"返回对象时,在某些情况下,首先尝试将对象视为右值,只有当失败时,才将其视为左值。
在 C++11 中,这些"某些情况"是"复制省略是可能的",这要求返回对象和返回类型是相同的类型(模 cv 限定)。
在C++14中,这些"某些情况"被放宽为"复制省略是可能的,或者返回的对象是函数中的局部变量"。
因此,在 C++11 中,代码失败,因为std::unique_ptr<Derived>
(derived
的类型)与std::unique_ptr<Base>
(返回类型)不同,因此必须使用std::move
。
在 C++14 中,代码成功,因为derived
是函数中的局部,因此首先被视为右值。这使得你引用的构造函数模板适用:
如果std::unique_ptr<T>
可以转换为T*
,则可以从std::unique_ptr<U>
类型的右值构造U*
。
您的 Clang 3.8 似乎表现出 C++11 行为;也许它尚未(尚未/完全)在该版本中实现 C++14 的宽松方面。
(是的,实际上您应该假设"模板类型"U
与类的模板参数T
不同。这就是首先引入它的原因:#6 描述的构造函数是一个构造函数模板)。
该return
调用unique_ptr
的转换移动构造函数模板,template<class U, class E> unique_ptr(unique_ptr<U, E>&&)
。没有省略;它取决于核心问题 1579 的解决方案所启用的隐式移动derived
。
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 使用strcpy将char数组的元素复制到另一个数组
- 是否可以初始化不可复制类型的成员变量(或基类)
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 复制列表初始化的隐式转换的等级是多少
- 当从函数参数中的临时值调用复制构造函数时
- 有可能在Armadillo中复制MATLAB circshift方法吗
- 复制几乎为空的数组的最快方法
- 以下示例中如何避免代码复制?C++/库达
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 不能将复制初始化与隐式转换的多个步骤一起使用
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- CLANG 编译器 说:变量"PTR"可能未初始化
- 文件系统:复制功能的速度秘诀是什么
- 为共享 ptr 向量实现复制 c'tor?
- 具有基类唯一ptr的类的复制构造函数