8

说一堂课

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当用户没有提供时,基本上是否有任何新的生成函数规则?

4

2 回答 2

7

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

默认构造函数

[class.ctor]/5

类的默认构造函数是可以在没有参数的情况下调用X的类的构造函数。X如果 class 没有用户声明X的构造函数,则没有参数的构造函数被隐式声明为默认值。隐式声明的默认构造函数是inline public其类的成员。如果[...很多点与此处无关],则将类的默认默认构造函数X定义为已删除。

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

默认析构函数

[class.dtor]

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

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

因此,在除 a) [使用用户声明的 dtor] 之外的所有情况下,默认 dtor 会被隐式声明并在使用 odr 时隐式定义。


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

复制构造函数

如果没有用户定义的 copy-ctor(ctor 模板永远不是 copy-ctor),则隐式声明 copy-ctor。[class.copy]/7

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

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

移动构造函数

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

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

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

因此,在任何情况下都没有声明move-ctor 。


复制赋值运算符

在 [class.copy]/18 中:

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

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

除了 e) [用户声明的复制分配操作] 之外,在所有情况下都声明了复制分配操作。在 b) 和 c) 中定义为删除 [both: user-declared move ctor];它可以在 a) [user-declared dtor] 和 d) [user-declared copy-ctor] 中定义为默认值。注意与copy-ctor的平行。

移动赋值运算符

与 move-ctor 类似,如果 [class.copy]/20 中的任何一个,甚至都不会声明 move-assignment 操作:

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

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

move-assignment-op 被隐式声明并在任何情况下都定义为默认值。

于 2013-10-26T13:07:38.437 回答
3

因此,查看一些帖子和在线教程,我得出了以下结论:

生成的函数:-

  • C++ 03:

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

    2) Copy Constructor(仅在用户声明5,6号时生成)

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

    4) 析构函数

  • 从 C++ 11 开始:

    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。

于 2013-10-26T13:47:46.563 回答