Конструктор закрытой копии с неназванным аргументом?

Я читал некоторый код C++ из базового эмулятора процессора, и я просто не могу этого понять:

class CPU {
private:
    CPU (const CPU&){}
};

Я понимаю указатели, я также проверил это: Ampersand & с const в конструкторе. По-видимому, это (жесткий) конструктор копирования, но я не понимаю, как это работает? почему константа? Почему амперсанд в конце без имени var? Почему частный? Я не нашел подобного примера ни в своих книгах, ни на сайте cplusplus.com.

На заметку:

int foo(int var)  { cout << var; }
int bar(int &var) { cout << var; }

foo и bar печатают одно и то же? bar по сути печатает *&var?

Любая помощь приветствуется!


person ShadoWalkeR    schedule 26.11.2013    source источник


Ответы (4)


& указывает на передачу по ссылке при использовании в определениях аргументов. Это преобразует аргумент в указатель и отменяет ссылку на этот указатель, когда вы используете его в области действия функции. В вашем втором вопросе обе функции печатают одно и то же, потому что & просто говорит передать исходный объект по ссылке, а не копировать его в заголовок функции. Существует одно и то же содержимое, единственная разница в том, что одна из функций копирует полный ввод, а другая может редактировать исходную переменную, если захочет.

CPU (const CPU&){} говорит, что конструктору требуется постоянная ссылка на объект ЦП. Это означает, что вы можете получить доступ только к константным функциям ЦП (и гарантировать, что вы не измените исходный аргумент объекта ЦП). Отсутствие имени после CPU& просто означает, что вы не присваиваете переменной имя в текущей области видимости (например, скобки после определения игнорируют аргумент).

Когда конструктор является закрытым, это обычно означает, что есть другая функция, которая будет генерировать объект для вас. Фабрики часто скрывают конструктор объектов и требуют некоторых других атрибутов/регистрации, прежде чем создавать объект для вас.

person Pyrce    schedule 26.11.2013
comment
Таким образом, конструктор закрытой копии можно использовать для управления количеством экземпляров и предотвращения копирования экземпляра? Интересный. Спасибо. - person ShadoWalkeR; 27.11.2013

Это не работает. Рабочее слово здесь private. Что делает вся эта конструкция, так это создает конструктор копирования, который может быть вызван только из функции-члена, эффективно отключая это поведение. Обычно люди пропускают тело функции, так что вы также получите ошибку ссылки, если вызовете ее из функции-члена.

На языке С++ 11 это будет реализовано как

CPU(const CPU&) = delete;

Если вы действительно пытались его вызвать:

CPU x;
CPU y(x); // this is the one that matches the parameters

вы получите ошибку компилятора, потому что вы не являетесь функцией-членом, но пытаетесь вызвать частную функцию.

Причина, по которой они сделали это, заключается в том, что они хотят отключить функциональность — вы не можете создать один из этих объектов с помощью конструктора копирования.

«const CPU&» означает «взять ссылку на const CPU». Не указывать имя переменной допустимо, поскольку функция никогда не ссылается на него, но оно должно соответствовать шаблону аргумента.

person kfsone    schedule 26.11.2013
comment
На самом деле это «может работать», если другие методы ЦП используют конструктор копирования (хотя это маловероятно) - person Pyrce; 27.11.2013
comment
@Pyrce: Вот почему обычно тело не определяется. Поэтому, если он случайно используется, вы получите ошибку компоновщика. Но именно поэтому =delete лучше, так как вам не нужно помнить, чтобы не определять его. - person Martin York; 27.11.2013
comment
Что значит не работает? кажется, что это код в существующем проекте, и большинство проектов C++ по-прежнему написаны на C++03 в лучшем случае, где это способ скрыть конструктор копирования от других классов. - person Iuri Covalisin; 27.11.2013
comment
Полезная информация не знал, что вы можете предотвратить такое копирование. @IuriCovalisin main в этом коде не использует ctor копирования. Спасибо. - person ShadoWalkeR; 27.11.2013
comment
@ShadoWalkeR: main не может использовать copy ctor - это цель сделать его приватным, чтобы компилятор не работал, если кто-то попытается его вызвать. - person Iuri Covalisin; 27.11.2013
comment
Предоставление ему пустого тела функции обычно означает, что кто-то ошибается. Это обеспечивает неправильную реализацию (ничего не делает, оставляет сконструированный объект неинициализированным), и если вы по ошибке получите доступ к функции внутри функции-члена, вы не получите предупреждения, только случайные ошибки. - person kfsone; 27.11.2013

  1. const, потому что вы не изменяете копируемый объект
  2. Амперсанд означает ссылку
  3. имя аргумента не допускается в объявлении метода, потому что имеет значение только тип, а не имя

И, наконец, private - этот код просто "скрывает" конструктор копирования от других классов, что означает "не копируйте меня".

person Iuri Covalisin    schedule 26.11.2013

Это способ предотвратить (случайное) создание копии экземпляра вашего класса с помощью e.q. передать его функции:

CPU foo;
void f1(CPU &foo) {}; f1(foo);  // work
void f2(CPU *foo) {}; f2(&foo); // work
void f3(CPU foo)  {}; f3(foo);  // fails

Таким образом, вы не сможете вставить его в функцию вызова по значению.

person Abubadabu    schedule 27.11.2013