You are here:

C++/What is exact syntax of copy constructor

Advertisement


Question
I am little bit confused with the copy constructor.
whats the exact syntax?
1= Class_Name( Class_Name& object_name )
2= Class_Name( const Class_Name& object_name )
3= Class_Name(  Class_Name object_name )

no.3 is error by compilers?Why?
Is there any way to execute no.2 copy constructor, if both 1 and 2 are present?Bcoz- compiler optimized the code where RValue is passed to initialize an object, and call constructor, not copy constructor.

Answer
Hello there.

Well, the _usual_ form of a copy constructor is your option 2:

   Class_Name( const Class_Name& object_name )

or the equivalent:

   Class_Name( Class_Name const & object_name )

that is we pass a _reference_ to a constant object.

We pass a reference to const because usually (99.9999%+ of cases) we should not have to modify what we are copying.

In a few edge cases we might wish to modify the object that is copied in which case we use the:

   Class_Name( Class_Name& object_name )

form (your option 1). That is we pass a reference to a mutable object.

However the pass by value form (your option 3):

   Class_Name(  Class_Name object_name )

cannot work because pass by value means we make a _copy_ of the passed in parameter. To make a copy we need to call the copy constructor, which passes the object to be copied by value which means we make a copy of the passed in parameter. To make a copy we need to call the copy constructor... I hope you get the point.

If both a reference to const object and reference to mutable object forms of copy constructor (your options 2 & 1) exist then the former is called for const objects, including rvalues, and the latter for mutable objects - i.e. usual non-const 'variables'.

You can create a constant object by declaring it const when it is created:

   C const constant_c(...);
(where ... indicates parameters to construct a C object)

Note that this would be an out of the ordinary thing to do and your compiler may well issue a warning to the effect that such a class has more than one copy constructor.

Further note that in some cases - including with rvalue parameters, as I think you allude to in your question - a compiler can and quite probably will - elide (remove) unnecessary copies, however a reachable appropriate copy constructor must still exist even if the compiler works out it can do without actually calling it. So code such as:

   C copy_rvalue = C(...);

(where ... indicates parameters to construct a C object) would seem to require construction of a temporary rvalue C object from whatever parameters which is then copied to the copy_rvalue C object. However, while an appropriate copy constructor must be available it is probable the compiler will elide the copy and, as you say, just call the construct from parameters constructor as an optimisation. You might try such a copy form rvalue initialisation for a class with only a copy constructor taking a reference to mutable type (your option 1 form).

Here is a simple full example (DISCLAIMER: this is not intended to be good code, its only use is to demonstrate the points made above):

   class C
   {
       int a;

   public:
       C(C const & c) : a(c.a)
       {
         std::cout << "Copying CONST C. C::a=" << a << "\n";
       }

       C(C & c) : a(c.a)
       {
         std::cout << "Copying MUTABLE C. C::a=" << a << "\n";
       }

       C() : a(0) {}

       C(int a) : a(a) {}
   };

   int main()
   {
       C mut(1);
       C copy_mut(mut);
       C copy_rvalue = C(2);
       C const con(3);
       C copy_con(con);
   }

(built and run with MS Visual C++ 2012 (debug x64 build with optimisations disabled), and g++ 4.7.3 x64 (with options -Wall -pedantic). Both elided the copy_rvalue copy constructor call. Add -fno-elide-constructors to g++ command line options to prevent g++ build from eliding call to C(C const & c) for copy_rvalue case; do not think MSVC++ has a similar option).

In C++11 there is a new category of reference type called an rvalue reference, and a constructor taking an rvalue reference to an object of the constructor's class type is called a move constructor. Because rvalues are temporary and are only really useful until the call completes it is safe to move their resources to the target object of the move, ripping the guts out of the referenced temporary. This is generally only useful if class instances own resources indirectly - such as a string or vector having a pointer to an array of data. In such cases moving the pointed to resources from the temporary to the target object by just copying their pointers is generally a lot quicker than allocating new storage (possibly also initialising it) and copying each item from the temporary source object to the target object for each such resource. Note that before returning from the constructor call the temporary source object's resource references (pointer members) must be modified so they are in a state such that they do not destroy and deallocate the resources when the temporary object is destroyed as the resources are now owned by the target object of the move. Hence move constructors take rvalue references to mutable objects.

Rvalue references and move semantics can get quite involved, a bit too involved to go into in depth here. However there are plenty of articles and Q&As out there on the WWW. Try queries such as:

   C++ rvalue reference
   C++ move constructor
   C++ universal reference

in your search engine of choice to find some such articles and Q&As.

Oh, and remember: if you need copy and/or move construction you generally also require copy and/or move assignment (operator=).

So in short:

   - decide if a type needs to be copy/assignable and/or move/assignable (C++11 and later only)

   - if so determine whether you need to define your own copy/move/assignment operations or whether the
     compiler provided defaults will suffice (in many cases they will)

   - of those types that require user defined copy/move construction and assignment the usual declarations are:
   
       Class_Name( Class_Name const & other )          // Copy construct from reference to constant object
       Class_Name( Class_Name && other )          // Move construct from rvalue reference to mutable object
       Class_Name & operator=( Class_Name const & rhs )    // Copy assign from reference to constant object
       Class_Name & operator=( Class_Name && rhs )         // Move assign from rvalue reference to mutable object

   - finally, if you require user defined copy and/or move semantics it means you usually are managing resources
     that require some cleanup, hence if you define user copy/move/assignment operations you usually also require
     user defined destructor unless you are using Resource Acquisition Is Initialisation (RAII) (managed or
     smart resource) types for the resource-handling class instance members.

See: C++ rule of three
(and since C++11: C++ rule of five)

for example:

  http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)

and: RAII

Hope this helps.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.