2009-04-14 2 views
10

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

Как так:

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

вместо:

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

Спасибо заранее.


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

ответ

1

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

4

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

19

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

1

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

1

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

1

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

2

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

1

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

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

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

-1

Вы можете написать совершенно допустимый конструктор копирования и по-прежнему иметь возможность передавать ссылку, которая является 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 проходит через, вы должны проверить его в теле конструктора и выполнить инициализацию оттуда.

Не забывайте, что есть несколько моментов, с :: оператором функции =(), чтобы быть в курсе ...

+1

Вы не можете получить нулевую ссылку, не прибегая к непредсказуемому поведению в этом коде. Тестирование для NULL после того, как факт не является полезным, поскольку ошибка находится в другом коде. Фактически, компилятор может оптимизировать тест 'if (& MyClassCopy == NULL)', потому что он никогда не может произойти в правильной программе. –

+0

Я согласен с тем, что разыменование указателя NULL является недопустимой операцией, и тест для NULL лучше всего делать до операции разыменования. Однако, поскольку NULL можно назначить во время выполнения, большинство компиляторов позволят вам создать ссылку NULL, и компилятор не сможет проверить его. или оптимизировать тест для NULL out. Вы можете попробовать его с помощью g ++, и тест работает. – Rob

+0

После момента отражения вы правы, вы ДОЛЖНЫ тестировать нуль перед операцией разыменования. Тест после факта действительно не определен. – Rob

Смежные вопросы