繁体   English   中英

为什么删除模板复制构造函数会导致赋值运算符失灵?

[英]Why delete of templete copy constructor cause assignment operator disfunctional?

我有如下代码,看起来有点令人困惑。 我定义了一个模板 class。 它有一个用户定义的构造函数。 当我通过“operator =”声明此模板 class 的两个对象时,它的用户定义构造函数被调用,令我惊讶。 此外,删除其复制构造函数后,甚至在解析“operator =”期间编译也无法通过。 模板构造函数的规则是否与非模板 class 不同?

#include "iostream"
using namespace std;

template <typename T>
class MyPtr
{
private:
    T p_;
public:
    MyPtr(T P = NULL): p_(P)
    {
        cout<<"track!!"<<endl;
    }

    //MyPtr(const MyPtr<T> & P) = delete;
    ~MyPtr()
    {
 
    }
};

int main()
{
    int i=3;
    int j=4;
    MyPtr<int> p = i;
    MyPtr<int> pp = j;
}

模板构造函数的规则是否与非模板 class 不同?

不。

MyPtr<int> p = i; (和MyPtr<int> pp = j; )是 复制初始化 请注意,这是初始化而不是赋值,因为效果p由构造函数MyPtr::MyPtr(T)初始化。 例如

MyPtr<int> p = i; // initialization; constructors get called
p = j;            // assignment; assignment operators (operator=) get called

在 C++17 之前, i会先通过MyPtr::MyPtr(T)转换为MyPtr<int> ,然后将转换结果,即临时MyPtr<int>复制/移动以初始化p 即使允许优化复制/移动操作,也需要可访问复制/移动构造函数。 将复制构造函数声明为delete会使复制构造函数不可用并且不会生成移动构造函数,从而使MyPtr<int> p = i; 格式不正确,直到 C++17。

由于 C++17 优化是强制性的,并且复制/移动构造函数不需要再次访问,这意味着您的代码可以在 C++17 模式下正常编译,即使将复制构造函数声明为delete

  • 如果 T 是 class 类型,并且 other 的类型的 cv-unqualified 版本不是 T 或派生自 T,或者如果 T 是非类类型,但 other 的类型是 class 类型,用户定义的转换序列检查可以从 other 的类型转换为 T 的类型(或者如果 T 是 class 类型并且转换 function 可用,则转换为从 T 派生的类型)进行检查,并通过重载决议选择最佳的。 如果使用了转换构造函数,则转换结果是一个prvalue temporary (until C++17) prvalue expression (since C++17) ,然后用于直接初始化object。 The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM