Копировать конструкторы - c ++ - PullRequest
10 голосов
/ 14 апреля 2009

Могу ли я написать конструктор копирования, просто передав указатель вместо константной ссылки? (Было бы хорошо, если бы я убедился, что я не собираюсь менять какие-либо значения?)

Вроде так:

SampleClass::SampleClass(SampleClass* p)
{
 //do  the necessary copy functionality
}

вместо:

SampleClass::SampleClass(const SampleClass& copyObj)
{
//do the necessary copy
}

Заранее спасибо.


Спасибо всем. Итак, если я напишу конструктор, который принимает указатель (и думал, что это мой конструктор копирования), компилятор все равно снабдит конструктором копирования по умолчанию, и в этом случае мой конструктор (который я считал моим конструктором копирования) не будет будет вызван конструктор копирования по умолчанию. Понял.

Ответы [ 9 ]

19 голосов
/ 14 апреля 2009

Да, вы можете написать конструктор, который принимает указатель на объект. Однако его нельзя назвать конструктором копирования. Само определение конструктора копирования требует, чтобы вы передавали объект того же класса. Если вы передаете что-то еще, да, это нормально, но не конструктор копирования.

4 голосов
/ 14 апреля 2009

Вы можете написать конструктор, который принимает указатель в качестве аргумента.
Но конструктор копирования - это имя, которое мы даем конкретному конструктору.
Конструктор, который принимает ссылку (предпочтительно const, но не обязательно) того же класса, что и аргумент, просто называется конструктором копирования, потому что это то, что он делает эффективно.

2 голосов
/ 14 апреля 2009

Помимо того факта, что это не будет конструктор копирования, и компилятор сгенерирует конструктор копирования, если вы явно не отключите его, выиграть нечего и многое можно потерять. Какова правильная семантика для конструктора из нулевого указателя? Что это добавляет к пользователю вашего класса? (Подсказка: ничего, если она хочет создать объект из кучи, она может просто разыменовать указатель и использовать обычный конструктор копирования).

1 голос
/ 14 апреля 2009

Конструктор копирования неявно используется в двух случаях:

  • Когда экземпляр вашего класса передается по значению в функцию.
  • Когда экземпляр вашего класса возвращается по значению из функции.

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

1 голос
/ 14 апреля 2009

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

1 голос
/ 14 апреля 2009

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

1 голос
/ 14 апреля 2009

По определению, копия ctor использует константную ссылку. Хотя ничто не мешает вам написать ctor, который принимает указатель, он вызывает некоторые проблемы, которые отсутствуют при использовании ссылки - например, что должно / может произойти, если передан нулевой указатель?

1 голос
/ 14 апреля 2009

Нет. Конструкторы копирования должны иметь ссылку, а не указатель, если это необходимо для передачи по значению и т. Д.

0 голосов
/ 03 ноября 2011

Вы можете написать совершенно корректный конструктор копирования и при этом иметь возможность передавать ссылку на NULL. Вы можете проверить на NULL, но только если вы не используете списки инициализации конструктора.

Пример:

MyClass::MyClass( MyClass const& MyClassCopy )
: somevar( MyClassCopy.somevar ) // <- the init list goes here.
{
   // If MyClassCopy is NULL, the initialization above is doomed!
   // However we can check for NULL in the constructor body but
   // the initialization list must be removed ...
   if (&MyClassCopy == NULL ) throw( std::runtime_error("NULL pointer!"));
   somevar = MyClassCopy.somevar;
}

// I'll now do some very dangerous programming to
// demonstrate one way that a NULL can get through ...
MyClass* P = NULL;
MyClass A( *P ); // Bang, you're dead!

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

Не забудьте, что есть несколько ошибок с функцией :: operator = (), о которых нужно знать ...

...