Форум » C/C++ для начинающих (C/C++ for beginners) » Implicitly defined copy constructor and explicitly defined copy constructor: what is the difference? » Ответить

Implicitly defined copy constructor and explicitly defined copy constructor: what is the difference?

Сыроежка: Иногда можно встретить утверждение, что неявно определенный компилятором конструктор копирования эквивалентен следующему определенному пользователем конструктору копирования (будем считать, что класс позволяет определить неявно конструктор копирования с параметром в виде константной ссылки на объект класса) в тех случаях, когда класс не имеет собственных членов данных: [pre2] inline SomeClass( const SomeClass & ) {} [/pre2] Например при таком определении класса [pre2] struct A { A() {} A( const A & ) {} }; [/pre2] Однако на самом деле эти определения не эквиваленты, если класс имеет подобъект в виде базового класса Различие заключается в том, что определенный неявно компилятором конструктор копирования осуществляет копирование подобъекта базового класса, в то время как определенный пользователем таким образом, как показано выше, конструктор копирования не выполняет копирование базового класса а использует инициализацию своего подобъекта по умолчанию. Незнание этого может привести к трудно находимым ошибкам. Приведу соответствующие выдержки из стандарта C++, прежде чем показать пример, демонстрирующий это различие. В параграфе №15 раздела 12.8 Copying and moving class objects написано относительно неявно определенного конструктора копирования: [quote]15 The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move of its bases and members.[/quote] Что касается явно определенного пользователем конструктора копирования, то механизм создания подобъектов класса другой. Он описан в параграфе №8 раздела 12.6.2 Initializing bases and members стандарта C++: [quote]8 In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then — if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initialized as specified in 8.5; — otherwise, if the entity is an anonymous union or a variant member (9.5), no initialization is performed; — otherwise, the entity is default-initialized (8.5).[/quote] Наглядно продемонстрировать это различие можно на следующем простом примере: [pre2] #include <iostream> struct A { A() : i( 0 ) { std::cout << "A::A()" << std::endl; } A( int i ) : i( i ) {} A( const A &rhs ): i( rhs.i ) { std::cout << "A::A( const A & )" << std::endl; } int i; }; struct B : A { B( int i = 0 ) : A( i ) {} B( const B & ){} }; struct C : A { C( int i = 0 ) : A( i ) {} C( const C & ) = default; }; int main() { B b1( 10 ); B b2( b1 ); std::cout << "b2.i = " << b2.i << std::endl; C c1( 10 ); C c2( c1 ); std::cout << "c2.i = " << c2.i << std::endl; return 0; } [/pre2] В этом примере класс B имеет явно определенный пользователем конструктор копирования, а класс C имеет неявно определенный компилятором конструктор копирования. Результатом работы этого примера будет следующий вывод на консоль: [pre2] A::A() b2.i = 0 A::A( const A & ) c2.i = 10 [/pre2] который наглядно демонстрирует различие в работе этих двух конструкторов копирования. Этот пример можно использовать как тестовое задание, то есть представить код и спросить, каков будет вывод на консоль. Если программист знает различие между неявно определенным и явно определенным конструкторами копирования, то он даст правильный ответ. Если же не знает, то ответ будет неверным.

Ответов - 0



полная версия страницы