为什么删除模板副本构造函数会导致赋值运算符无法工作?

Caiyi Zhou

我有下面的代码,看起来有些混乱。我定义了一个模板类。它具有用户定义的构造函数。当我通过“ operator =”声明此模板类的两个对象时,令其惊讶的是调用了它的用户定义构造函数。此外,删除其副本构造函数后,即使在解析“ operator =“的过程中,编译也无法通过。Templete构造函数的规则与非Templete类的规则不同吗?

#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;
}
songyuanyao

Templete构造函数的规则与非Templete类的规则不同吗?

不。

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之前,首先iMyPtr<int>通过转换为MyPtr::MyPtr(T),然后将转换结果(即临时文件MyPtr<int>被复制/移动以初始化)p即使允许复制/移动操作被优化,复制/移动构造函数也必须可访问。将复制构造函数声明为asdelete会使复制构造函数不可用,并且将不会生成move构造函数,因此会导致格式错误,MyPtr<int> p = i;直到C ++ 17为止。

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

  • 如果T是类类型,并且other的cv不合格版本不是T或不是从T派生的,或者T是非类类型,但是other的类型是类类型,则用户定义的转换序列可以将其他类型转换为T(如果T是类类型并且可以使用转换函数,则可以转换为从T派生的类型),然后通过重载分辨率选择最佳的类型。转换结果(prvalue temporary (until C++17) prvalue expression (since C++17)如果使用了转换构造函数,则为a)然后用于直接初始化对象。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)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么删除模板副本构造函数会导致赋值运算符无法工作?

来自分类Dev

为什么要单例删除move构造函数和move赋值运算符?

来自分类Dev

为什么以及何时删除副本构造函数和运算符=

来自分类Dev

.NET CLI为什么不为参考类提供综合的副本构造函数和赋值运算符?

来自分类Dev

双链列表模板副本构造函数赋值运算符

来自分类Dev

在赋值运算符中调用副本构造函数

来自分类Dev

子类化,赋值运算符和副本构造函数

来自分类Dev

为什么赋值运算符重载会创建对象的副本?

来自分类Dev

无法弄清楚为什么使用重载比较运算符在执行之前调用副本构造函数

来自分类Dev

为什么函数中本地定义的结构需要赋值运算符和复制构造函数

来自分类Dev

类的赋值运算符和副本构造函数,其中包含指向派生模板化类的基类指针

来自分类Dev

什么时候删除复制构造函数和赋值运算符?

来自分类Dev

为什么在调用重载的赋值运算符时调用了拷贝构造函数?

来自分类Dev

为什么不只有一个?复制构造函数和赋值运算符

来自分类Dev

为什么在赋值运算符之后在此代码中调用复制构造函数?

来自分类Dev

为什么在调用重载的赋值运算符时调用了拷贝构造函数?

来自分类Dev

为什么我的运算符+重载尽管通过引用传递但仍调用我的副本构造函数?

来自分类Dev

从赋值运算符调用构造函数

来自分类Dev

构造函数中的赋值运算符

来自分类Dev

按值的赋值运算符不使用显式副本构造函数进行编译

来自分类Dev

为什么有人应该创建一个默认的move构造函数,但要删除move赋值运算符?

来自分类Dev

为什么会这样呢?运算符=和复制构造函数

来自分类Dev

为什么构造函数会优先于用户定义的运算符?

来自分类Dev

为什么在对象初始化时可以通过赋值运算符将参数传递给构造函数?

来自分类Dev

c ++(为什么)确实移动构造函数删除运算符=

来自分类Dev

为什么引用类型成员导致隐式声明的副本分配运算符被删除

来自分类Dev

删除副本构造函数会导致删除默认构造函数

来自分类Dev

std :: swap在构造函数,赋值运算符和析构函数方面如何工作?

来自分类Dev

C ++中的赋值运算符模板和复制构造函数

Related 相关文章

  1. 1

    为什么删除模板副本构造函数会导致赋值运算符无法工作?

  2. 2

    为什么要单例删除move构造函数和move赋值运算符?

  3. 3

    为什么以及何时删除副本构造函数和运算符=

  4. 4

    .NET CLI为什么不为参考类提供综合的副本构造函数和赋值运算符?

  5. 5

    双链列表模板副本构造函数赋值运算符

  6. 6

    在赋值运算符中调用副本构造函数

  7. 7

    子类化,赋值运算符和副本构造函数

  8. 8

    为什么赋值运算符重载会创建对象的副本?

  9. 9

    无法弄清楚为什么使用重载比较运算符在执行之前调用副本构造函数

  10. 10

    为什么函数中本地定义的结构需要赋值运算符和复制构造函数

  11. 11

    类的赋值运算符和副本构造函数,其中包含指向派生模板化类的基类指针

  12. 12

    什么时候删除复制构造函数和赋值运算符?

  13. 13

    为什么在调用重载的赋值运算符时调用了拷贝构造函数?

  14. 14

    为什么不只有一个?复制构造函数和赋值运算符

  15. 15

    为什么在赋值运算符之后在此代码中调用复制构造函数?

  16. 16

    为什么在调用重载的赋值运算符时调用了拷贝构造函数?

  17. 17

    为什么我的运算符+重载尽管通过引用传递但仍调用我的副本构造函数?

  18. 18

    从赋值运算符调用构造函数

  19. 19

    构造函数中的赋值运算符

  20. 20

    按值的赋值运算符不使用显式副本构造函数进行编译

  21. 21

    为什么有人应该创建一个默认的move构造函数,但要删除move赋值运算符?

  22. 22

    为什么会这样呢?运算符=和复制构造函数

  23. 23

    为什么构造函数会优先于用户定义的运算符?

  24. 24

    为什么在对象初始化时可以通过赋值运算符将参数传递给构造函数?

  25. 25

    c ++(为什么)确实移动构造函数删除运算符=

  26. 26

    为什么引用类型成员导致隐式声明的副本分配运算符被删除

  27. 27

    删除副本构造函数会导致删除默认构造函数

  28. 28

    std :: swap在构造函数,赋值运算符和析构函数方面如何工作?

  29. 29

    C ++中的赋值运算符模板和复制构造函数

热门标签

归档