Я немного смущен относительно механики конструктора копии. Исправьте меня, если я неправ:
Если метод берет ссылку на объект в качестве параметра, и класс определяет копию construtor, то класс использует конструктора для создания копии себя, и это передается функции вместо ссылки на исходный объект?
Кроме того, можно звонить
Object * obj = new Object(&anotherObject);
создать копию anotherObject?
Нет, если функция принимает ссылку:
void f1( Object & o ); // call by reference
, то копирование не производится. Если функция принимает значение:
void f2( Object o ); // call by value
, то копия создается компилятором с помощью конструктора копирования.
И да, когда вы говорите:
Object * obj = new Object(anotherObject); // not &anotherObject
конструктор копирования используется явно (при условии, что anotherObject имеет тип Object.) Однако здесь нет ничего волшебного в использовании new
- в данном случае :
Object obj2(anotherObject);
также используется конструктор копирования.
Если метод принимает ссылку на объект в качестве параметра , конструктор копирования не вызывается. Если бы это было так, то вызов самого конструктора копирования привел бы к бесконечному циклу (поскольку он принимает ссылку в качестве аргумента).
Эта строка не является допустимым способом вызова конструктора копирования. Он ожидает ссылку в качестве аргумента, а не указателя.
Конструктор копирования вызывается только при передаче по значению , а не по ссылке . По ссылке копирование не требуется (это часть того, для чего нужны ссылки!), поэтому конструктор копирования не вызывается.
Тот факт, что вы вызываете метод, здесь не имеет значения. Инициализация ссылочного параметра во время вызова функции ничем не отличается от инициализации автономной ссылки и регулируется теми же правилами.
Правила инициализации ссылки немного сложны, но суть в том, что если инициализатором является lvalue (аргумент в вызове метода в вашем случае) и тип ссылки такой же, как тип инициализатор (т.е. тип параметра совпадает с типом аргумента), тогда ссылка будет привязана напрямую. Т.е. копия не создается.
Object a; // class type
Object &r = a; // no copying
const Object &cr = a; // no copying
Если эти требования не выполняются (например, если инициализатором является rvalue), все зависит от ситуации. В некоторых случаях копирование может иметь место и будет иметь место. Например,
const Object &tr = Object();
может интерпретироваться компилятором как
const Object &tr = Object(Object(Object(Object())));
с конечным числом копий, зависящим от реализации. Конечно, из соображений эффективности компиляторы обычно стараются не создавать ненужных копий, даже если им разрешено копировать.
Классическим примером, который часто вызывает споры о допустимости копирующего поведения компилятора, является инициализация ссылки в выражениях, подобных приведенному ниже
Object a;
const Object &r = <some condition> ? a : Object();
Человек, знакомый с семантикой ссылок C ++, поймет, что выражения, подобные приведенным выше, скорее всего, являются обоснование стандартного разрешения на выполнение избыточного копирования во время инициализации ссылки.
Нет в обоих случаях. В первом случае передается ссылка на сам объект, и копия не создается. Во втором случае вы передаете указатель на конструктор объекта
, поэтому копия не создается. Поэтому у объекта должен быть конструктор (не конструктор копии), что-то вроде object(anotherClass*)