我认为数组是不可复制的

Mar*_*ork 13 c++ arrays copy-constructor assignment-operator

我的印象是阵列是不可复制的(或可分配的).

int x[5] = {1,2,3,4,5};
int y[5] = {6,7,8,9,0};

x = y; // Fails to compile
Run Code Online (Sandbox Code Playgroud)

但是当我在一个类中放入一个数组时,复制构造函数和赋值运算符工作(我会按预期说,但它不是我所期望的).

#include <iostream>

struct X
{
    virtual ~X(){} // Just in case it was something to do with POD 
                   // make sure its not a POD
    int x[5];
};

int main()
{
    X   a;

    a.x[0]  = 0;
    a.x[1]  = 1;
    a.x[2]  = 2;
    a.x[3]  = 3;
    a.x[4]  = 4;

    // Make a copy of a and test it
    X   b(a);          
    std::cout << a.x[0] << " : " << b.x[0] << "\n";

    b.x[0]  = 10;
    b.x[1]  = 11;
    b.x[2]  = 12;
    b.x[3]  = 13;
    b.x[4]  = 14;

    // Now that we have modified 'b' make sure it is unique.
    std::cout << a.x[0] << " : " << b.x[0] << "\n";

    // Use assignment and see if it worked.
    b   = a;
    std::cout << a.x[0] << " : " << b.x[0] << "\n";
}
Run Code Online (Sandbox Code Playgroud)

编译并运行

> g++ t.cpp
> ./a.out
0 : 0
0 : 10
0 : 0
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?

Ben*_*igt 20

默认的复制构造函数和赋值运算符分别对每个成员使用复制构造和赋值.当有数组时,在数组的每个元素上使用复制构造或赋值(这是非常明确的).

这是规则,从12.8节([class.copy])开始:

非联合类的隐式定义的复制/移动构造函数X执行其基础和成员的成员复制/移动.[注意:忽略非静态数据成员的大括号或大小写.另请参见12.6.2中的示例. - 结束注释]初始化的顺序与用户定义的构造函数中基数和成员的初始化顺序相同(见12.6.2).让我们x为构造函数的任何参数,或者对于移动构造函数,x值指的是参数.以适合其类型的方式复制/移动每个基本或非静态数据成员:

  • 如果成员是一个数组,则每个元素都使用相应的子对象进行直接初始化x ;
  • 如果成员m具有右值引用类型T&&,则直接初始化为static_cast<T&&>(x.m);
  • 否则,基础或成员用相应的基础或成员直接初始化x.

非联合类的隐式定义的复制/移动赋值运算符X执行其子对象的成员复制/移动分配.直接基类X按照它们在base-specifier-list中的声明顺序首先分配,然后按照X它们在类定义中声明的顺序分配直接非静态数据成员.我们x是函数的任何参数,或者,对于移动运营商的x值指的是参数.每个子对象都以适合其类型的方式分配:

  • 如果子对象是类类型,就好像通过调用operator =将子对象作为对象表达式而x的对应子对象作为单个函数参数(就像通过显式限定;即忽略任何可能的虚拟覆盖函数在更多派生类中);
  • 如果子对象是一个数组,则以适合于元素类型的方式分配每个元素 ;
  • 如果子对象是标量类型,则使用内置赋值运算符.

C::C(const C&)vs C::C(C&)et al 之间的签名选择规则还包括引用数组元素类型的语言.