Можно ли явно вызвать конструктор копирования?
Я немного смущен относительно механики конструктора копирования. Исправьте меня, если я ошибаюсь:
Если метод принимает ссылку на объект в качестве параметра, а класс определяет конструктор копирования, то класс использует конструктор для создания копии самого себя и который передается функции вместо ссылки на оригинал объект?
Кроме того, можно назвать
Object * obj = new Object(&anotherObject);
создать копию другого объекта?
Ответы
Ответ 1
Нет, если функция принимает ссылку:
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);
используется также конструктор копирования.
Ответ 2
Если метод принимает ссылку на объект как параметр, конструктор копирования не будет вызываться. Если это так, то вызов самого конструктора копирования привел бы к бесконечному циклу (поскольку он принимает ссылку как аргумент).
Эта строка не является допустимым способом вызова конструктора копирования. Он ожидает ссылку как аргумент, а не указатель.
Ответ 3
То, что вы делаете вызов метода, здесь не имеет значения. Инициализация ссылочного параметра во время вызова функции ничем не отличается от инициализации автономной ссылки и определяется теми же правилами.
Правила инициализации ссылок немного сложны, но в нижней строке указано, что если инициализатор является lvalue (аргумент в вызове метода в вашем случае), а тип ссылки такой же, как тип initializer (т.е. тип параметра совпадает с типом аргумента), тогда ссылка будет связана напрямую. То есть копия не создается.
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();
Лицо, знакомое с семантикой ссылок С++, понимает, что выражения, подобные приведенным выше, скорее всего, являются обоснованием стандартного разрешения на выполнение избыточного копирования во время инициализации ссылки.
Ответ 4
Нет в обоих случаях. В первом случае передается ссылка на этот объект и копия не создается. Во втором случае вы передаете указатель на конструктор object
, поэтому копия не создается. Таким образом, объект должен иметь конструктор (не конструктор копирования), который является чем-то вроде object(anotherClass*)
Ответ 5
Конструктор копирования вызывается только при передаче по значению, а не по ссылке. Посредством ссылки не требуется копирование (это часть ссылок для!), Поэтому не вызвал конструктор копирования.
Ответ 6
да, используя новое размещение так:
Object dstObject;
new(&dstObject) Object(&anotherObject);