Я думал, что массив не для копирования - PullRequest
13 голосов
/ 07 февраля 2012

У меня сложилось впечатление, что массив нельзя копировать (или назначать).

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

x = y; // Fails to compile

Но когда я помещаю массив в класс, конструктор копирования и оператор присваивания работают (я бы сказал, как ожидалось, но это не то, что я ожидал).

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

Компиляция и запуск

> g++ t.cpp
> ./a.out
0 : 0
0 : 10
0 : 0

Что здесь происходит?

Ответы [ 2 ]

20 голосов
/ 07 февраля 2012

Конструктор копирования по умолчанию и оператор присваивания используют конструкцию и назначение копирования индивидуально для каждого члена. Когда есть массив, конструкция копирования или присваивание используется для каждого элемента массива (который довольно четко определен).

Вот правило из раздела 12.8 ([class.copy]):

Неявно определенный конструктор копирования / перемещения для класса, не являющегося объединением X выполняет пошаговое копирование / перемещение своих баз и членов. [Примечание: инициализаторы фигурных или равных скобок нестатических элементов данных игнорируются. Смотрите также пример в 12.6.2. - примечание к концу] Порядок инициализации такой же, как порядок инициализации баз и элементов в определяемом пользователем конструкторе (см. 12.6.2). Пусть x будет либо параметром конструктор или, для конструктора перемещения, значение x, ссылающееся на параметр. Каждый элемент базовых или нестатических данных копируется / перемещается способом, соответствующим его типу:

  • если элемент является массивом, каждый элемент инициализируется напрямую с соответствующим подобъектом x;
  • если элемент m имеет ссылочный тип rvalue T&&, он инициализируется напрямую с static_cast<T&&>(x.m);
  • в противном случае база или элемент инициализируются напрямую с соответствующей базой или элементом x.

и

Неявно определенный оператор назначения копирования / перемещения для класса, не являющегося объединением X выполняет пошаговое назначение копирования / перемещения его подобъектов. Прямые базовые классы X назначаются первыми, в порядке их объявления в base-specier-list-list , а затем назначаются непосредственные нестатические члены данных X в порядок, в котором они были объявлены в определении класса. Пусть x будет либо параметром функции, либо, для оператора перемещения, значением x, относящимся к параметру. Каждый подобъект назначается способом, соответствующим его типу:

  • если подобъект относится к типу класса, как если бы он вызывался оператором = с подобъектом в качестве выражения объекта и соответствующим подобъектом x в качестве единственного аргумента функции (как будто с помощью явной квалификации; то есть игнорируя любые виртуальные переопределяющие функции в более производных классах);
  • если подобъект является массивом, каждому элементу присваивается способ, соответствующий типу элемента ;
  • если подобъект скалярного типа, используется встроенный оператор присваивания.

Правило выбора подписи между C::C(const C&) против C::C(C&) и др. Также включает язык, относящийся к типу элемента массива.

4 голосов
/ 07 февраля 2012

Массивы нельзя ни копировать, ни назначать.Однако структура с элементами массива сгенерировала конструкцию копии и назначение копии.Это специальное правило: т.е. они не должны быть копируемыми или назначаемыми сами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...