C++11 编译器生成的函数

C++11 compiler generated functions

本文关键字:函数 编译器 C++11      更新时间:2023-10-16

说一个类

class Piece {} ;

如果我是对的,那应该等同于:

class Piece {
   //C++ 03
    Piece ();                          //default constructor
    Piece( const Piece&);              //copy constructor
    Piece& operator=(const Piece&);    //copy assignment operator
    ~Piece();                          //destructor
    //Since C++ 11
    Piece(Piece&&);                   //move constructor
    Piece& operator=(Piece&&);        //move assignment operator
};

那么我能说些什么呢?

一)

class Pawn{
    ~Pawn() {}// Only destructor
};

b)

class Bishop{
    Bishop(Bishop&& ) {}// Only move constructor
};

c)

class Knight{
    Knight(Knight&&, int =0) {} // move constructor, when no second arg present
};

d)

class Rook {
    Rook(const Rook& ) {}// Only copy constructor
};

e)

class King{
        King& operator=(const King&) = delete;
    };

我的理解编译器将生成:

    a) 默认构造函数、复制构造函数、复制赋值运算符
  • 、( 移动构造函数/赋值运算符?
  • b) 析构函数
  • c) 析构函数
  • d) 复制赋值运算符和析构函数(移动构造函数/赋值运算符?
  • e) 默认构造函数、复制构造函数、析构函数、(移动构造函数/赋值运算符?

我在这里是否正确或遗漏了什么?

基本上,当用户不提供时,C++11是否有任何用于生成函数的新规则?

我将在这里省略一些不相关的要点,例如关于 union、基类、大括号或等于初始值设定项等。如果您的类有任何成员、基类、...那么答案会有所不同。例如,如果您有一个const成员,则隐式声明的赋值运算符将被定义为已删除。

默认构造函数

[类]/5

X的默认构造函数是类 X 的构造函数,无需参数即可调用。如果类 X 没有用户声明的构造函数,则没有参数的构造函数被隐式声明为默认值。隐式声明的默认构造函数是其类的inline public成员。类 X 的默认构造函数定义为删除,如果 [...很多观点在这里无关紧要]。

因此,在 a) 和 e) [没有任何用户声明的 ctor] 的情况下,默认 ctor 被声明为默认值。

默认析构函数

[类.dtor]

4 如果类没有用户声明的析构函数,则析构函数将隐式声明为默认值。隐式声明的析构函数是其类的inline public成员。

5 类X的默认析构函数定义为删除,如果 [...很多观点在这里无关紧要]

因此,在所有情况下,除了 a) [使用用户声明的 dtor],默认 dtor 被隐式声明,如果使用 odr,则隐式定义。


根据 [class.copy]/2+3,copy-ctor 和 move-ctor 可能有其他参数,如果它们有默认参数。

复制构造函数

如果没有用户定义的复制 ctor(ctor 模板从来都不是复制 ctor),则会隐式声明复制 ctor。[类.副本]/7

如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数定义为已删除;否则,它被定义为默认值。如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。

也就是说,在除 d) [使用用户声明的 copy-ctor] 之外的所有情况下,都会隐式声明 copy-ctor。在 b) 和 c) [使用用户提供的移动 ctor] 的情况下,复制 ctor 定义为已删除。对于 a) [用户声明的 dtor] 和 e) [用户声明的复制分配操作],它可能被定义为默认值,但这已被弃用。

移动构造函数

在这些情况下,甚至不会声明移动 ctor [class.copy]/9

  • X没有用户声明的复制构造函数,
  • X没有用户声明的复制赋值运算符,
  • X没有用户声明的移动分配运算符,
  • X没有用户声明的析构函数,并且
  • 移动构造函数不会隐式定义为已删除。
同样,在

相当多的情况下,它会被定义为删除,但它们在这里不适用。

因此,在任何情况下都不会声明移动。


复制赋值运算符

在 [class.copy]/18 中:

如果类定义未显式声明复制赋值运算符,则隐式声明一个。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制赋值运算符定义为已删除;否则,它被定义为默认值。如果类具有用户声明的复制构造函数或用户声明的析构函数,则不推荐使用后一种情况。

在某些情况下,它被定义为已删除,请参阅 [class.copy]/23,但它们在这里不适用。

在所有情况下都声明复制分配操作,但 e) [用户声明的复制分配操作]。它被定义为在b)和c)中删除[两者都:用户声明的移动ctor];它可以在 a) [用户声明的 dtor] 和 d) [用户声明的复制 CTOR] 中定义为默认值。请注意与复制者的并行。

移动赋值运算符

与 move-ctor 类似,如果 [class.copy]/20

  • X没有用户声明的复制构造函数,
  • X没有用户声明的移动构造函数,
  • X没有用户声明的复制赋值运算符,
  • X没有用户声明的析构函数,并且
  • 移动分配运算符不会隐式定义为已删除。

在某些情况下,它被定义为删除,请参阅 [class.copy]/23(与 copy-ctor 的段落相同),但它们在这里不适用。

移动分配操作是隐式声明的,并且在任何情况下都定义为默认值。

所以看了一些帖子和在线教程,我得出了这样的结论:

生成的函数:-

  • C++03:

    1) 默认构造函数(仅当用户未声明构造函数时才生成)

    2) 复制构造函数(仅在用户声明第 5、6 号时才生成)

    3) 复制赋值运算符(仅在用户未声明 5,6 时才生成)

    4) 析构函数

  • 自 11 C++以来:

    5) 移动构造函数(仅当用户未声明 2,3,4,6 时才生成)

    6) 移动赋值运算符(仅当用户未声明 2,3,4,5 时才生成)


所以,对于

一)

class Pawn{ //1, 2, 3
    ~Pawn() {}// Only destructor
};

b)

class Bishop{ //4
    Bishop(Bishop&& ) {}
};

c)

class Knight{ //4
    Knight(Knight&&, int =0) {} 
};

d)

class Rook { //3, 4
    Rook(const Rook& ) {}
};

e)

class King{ //1, 2, 4
        King& operator=(const King&) = delete;
    };

编辑:根据DyP评论:-

C++11,

对于情况 a),2 和 3 已弃用。

对于情况 d),不推荐使用 3。

对于情况 e),不推荐使用 2。