Copy Constructors and Assignment Operators

Copy Constructors and Assignment Operators: Just Tell Me the Rules! Part I

I get asked this question sometimes from seasoned programmers who are new to C++. There are plenty of good books written on the subject, but I found no clear and concise set of rules on the Internet for those who don't want to understand every nuance of the language—and just want the facts.

Hence this article.

The purpose of copy constructors and assignment operators is easy to understand when you realize that they're always there even if you don't write them, and that they have a default behavior that you probably already understand. Every struct and class have a default copy constructor and assignment operator method. Look at a simple use of these.

Start with a struct called Rect with a few fields:

struct Rect {
   int top, left, bottom right;
};

Yes, even a struct as simple as this has a copy constructor and assignment operator. Now, look at this code:

1: Rect r1 = { 0, 0, 100, 200 };
2: Rect r2( r1 );
3: Rect r3;
4: r3 = r1;

Line 2 invokes the default copy constructor for r2, copying into it the members from r1. Line 3 does something similar, but invokes the default assignment operator of r3, copying into it the members from r1. The difference between the two is that the copy constructor of the target is invoked when the source object is passed in at the time the target is constructed, such as in line 2. The assignment operator is invoked when the target object already exists, such as on line 4.

Looking at what the default implementation produces, examine what Line 4 ends up doing:

1. r3.top    = r1.top;
2. r3.left   = r1.left;
3. r3.bottom = r1.bottom;
4. r3.right  = r1.right;

So, if the default copy constructor and assignment operators do all this for you, why would anyone implement their own? The problem with the default implementations is that a simple copy of the members may not be appropriate to clone an object. For instance, what if one of the members were a pointer that is allocated by the class? Simply copying the pointer isn't enough because now you'll have two objects that have the same pointer value, and both objects will try to free the memory associated with that pointer when they destruct. Look at an example class:

class Contact {
   char* name;
   int age;
public:
   Contact( const char* inName, inAge ) {
   name = new char[strlen( inName ) + 1];
   strcpy( name, inName );
   age = inAge;
   }
   ~Contact() {
      delete[] name;
   }
};

Now, look at some code that uses this class:

Contact c1("Fred", 40 );
Contact c2 = c1;

The problem is, c1 and c2 will have the same pointer value for the "name" field. When c2 goes out of scope, its destructor will get called and delete the memory that was allocated when c1 was constructed (because the name field of both objects have the same pointer value). Then, when c1 destructs, it will attempt to delete the pointer value, and a "double-free" occur. At best, the heap will catch the problem and report an error. At worst, the same pointer value may, by then, be allocated to another object, the delete will free the wrong memory, and this will introduce a difficult-to-find bug in the code.

The way you want to solve this is by adding an explicit copy constructor and an assignment operator to the class, like so:

Contact( const Contact& rhs ) {
   name = new char[strlen( rhs.name ) + 1];
   strcpy( name, rhs.name );
   age = rhs.age;
}

Contact& operator=( const Contact& rhs ) {
   char* tempName = new char[strlen( rhs.name ) + 1];
   delete[] name;
   name = tempName;
   strcpy( name, rhs.name );
   age = rhs.age;
   return *this;
}

Now, the code that uses the class will function properly. Note that the difference between the copy constructor and assignment operator above is that the copy constructor can assume that fields of the object have not been set yet (because the object is just being constructed). However, the assignment operator must handle the case when the fields already have valid values. The assignment operator deletes the contents of the existing string before assigning the new string. You might ask why the tempName local variable is used, and why the code isn't written as follows instead:

delete[] name;
name = new char[strlen( rhs.name ) + 1];
strcpy( name, rhs.name );
age = rhs.age;

The problem with this code is that if the new operator throws an exception, the object will be left in a bad state because the name field would have already been freed by the previous instruction. By performing all the operations that could fail first and then replacing the fields once there's no chance of an exception from occurring, the code is exception safe.

Note: The reason the assignment operator returns a reference to the object is so that code such as the following will work:

c1 = c2 = c3;

One might think that the case when an explicit copy constructor and assignment operator methods are necessary is when a class or struct contains pointer fields. This is not the case. In the case above, the explicit methods were needed because the data pointed to by the field is owned by the object. If the pointer is a "back" (or weak) pointer, or a reference to some other object that the class is not responsible for releasing, it may be perfectly valid to have more than one object share the value in a pointer field.

There are times when a class field actually refers to some entity that cannot be copied, or it does not make sense to be copied. For instance, what if the field were a handle to a file that it created? It's possible that copying the object might require that another file be created that has its own handle. But, it's also possible that more than one file cannot be created for the given object. In this case, there cannot be a valid copy constructor or assignment operator for the class. As you have seen earlier, simply not implementing them does not mean that they won't exist, because the compiler supplies the default versions when explicit versions aren't specified. The solution is to provide copy constructors and assignment operators in the class and mark them as private. As long as no code tries to copy the object, everything will work fine, but as soon as code is introduced that attempts to copy the object, the compiler will indicate an error that the copy constructor or assignment operator cannot be accessed.

To create a private copy constructor and assignment operator, one does not need to supply implementation for the methods. Simply prototyping them in the class definition is enough. Example:

private:
Contact( const Contact& rhs );
Contact& operator=( const Contact& rhs );

Some people wish that C++ did not provide an implicit copy constructor and assignment operator if one isn't provided. They automatically define a private copy constructor and assignment operator automatically when they define a new class. That way, it will prevent anyone from copying their object unless the explicitly support such an operation. This is generally a good practice.



About the Author

Kenneth Kasajian

Development

Comments

  • Wholesale Oakley Break Point good quality

    Posted by vdzvfjnqi on 07/04/2013 03:12pm

    FoAkLey ,No-one believes you, no one ready to focus on you? But I think that everything becomes more perfect, you will need imagination. Typical Oakley style, striking colors and ultra-sound lenses and frames will be the ultimate expression of fashion, let him come to the fore! Oakley sunglasses are invariably leading in the field of science, the application of high-tech, to make sure they all the time beyond the limit, the exam in several projects, to check all possible to assume circumstances OAkley Hijinx SunglAsses ,Oakley, Sunglasses delicious array of rich colors, from chocolate to berry, flat every skin tone and hair color to take a position. Oakley sunglasses are not only seen avoid the sun, even so the other hit the decorative surface. The trendy appearance and fashion style, will probably be your option. Sunglasses are used everyday, giving her a very accessories of goods plus focuses on sporting activities and actions, whether you choose something plain and chic or a bright and unique. Oakley sunglasses additional protection vision, since the lens draped over your WATS remain more moderate as opposed to standard lens and ultraviolet radiation can result in further reluctant to implement a broad wide-brimmed sun defense. Fake Oakleys ,Sun block is usually destined to not merely know that you've got already installed an even more stylish plus more attractive appearance, that's actually a terrific way to. The most crucial and innovative style, code and data collection of posters within the 2012 sunglasses summer preparation, really the only products which could you are going on a break the most effective partner? Fake ray bans ,Cheap Oakley sunglasses, individuals have to be able to quickly accommodate their vision, and allow every possible advantage. Oakley anti-aircraft guns jacket XLJ There are various types for you to choose! Oakley sunglasses will always be revolutionary design and suspension system framework that it's going to not affect the optical lens. Sac En Bandoulière Longchamp ,The most beneficial-selling sunglasses, particularly for ladies fashion sunglasses, you are able to create a tremendous impact possesses its own personality. Also, the anti-collision function tests, 12 mm caliber shotgun. Different colors have different reflective coating can transfer 7%, 96% with the light, with assorted needs. What can you prefer the style, some designer sunglasses can improve from any of the equipment, and enables and keep your optical health.

    Reply
  • Short blog post illustrates the unquestionable info regarding chloe and how it could have an impact on you.

    Posted by emeseesip on 05/07/2013 09:17pm

    By Far The Most Comprehensive nike Guidebook You Ever Witnessed Otherwise Your Cash Back [url=http://www.guccija.biz/]グッチ キーケース[/url] Ok, amazing product. People got to have a look at gucci straight away whilst it is still in stock . . . [url=http://www.guccija.biz/]グッチ キーケース[/url] gucci will help every one of us by including a number of distinctive functions and capabilities. This is a unvaluable thing for every enthusiast of adidas. [url=http://www.guccija.biz/]グッチ トートバッグ[/url] Third party post unveils 2 brand new stuff regarding nike that not a soul is speaking of. [url=http://www.chanelja.biz/]シャネル バッグ[/url] The reasons no company is posting about adidas and the things you ought to take care of right away. [url=http://www.chanelja.biz/]chanel バッグ[/url] Most recent questions about adidas resolved and as a result why you should definitely look into every single phrase of this write up. [url=http://www.chanelja.biz/]財布 chanel[/url] The essential principles behind nike that you will advantage from starting off today.[url=http://www.nikeja.biz/]nike[/url] The best ways to comprehend all that there is to know relating to nike in Some basic steps.

    Reply
  • A significant double turn on adidas

    Posted by Updatatweda on 05/05/2013 10:11pm

    I [url=http://www.adidaskutuja.com/]adidas[/url] nmTmq SsqDon ObaYlq AjwN [url=http://www.adidaskutuja.com/adidas-originals-c-4.html]アディダス ランニング[/url] bgPpkKya UzzQujIemG [url=http://www.adidaskutuja.com/adidas-superstar-c-2.html]アディダス スタンスミス[/url] js SmdRyg [url=http://www.adidaskutuja.com/jeremy-scott-c-5.html]adidas ショップ[/url]AsyHyb BjdLxd

    Reply
  • Lightweight smart – Nike Loose TR Befit in spring 2013 3 series

    Posted by Tufffruntee on 04/24/2013 09:04am

    Nike Emancipated TR Fit 3 noteworthy features is to exploit the additional forge: Nike Let off 5 soles improved bending Gouge; stylish tractor layout making training more focused when; lighter preponderance, the permeability is stronger, and more fashionable shoe designs not just aim for shoes [url=http://markwarren.org.uk/goodbuy.cfm]nike free[/url] more pleasant wearing, barefoot training have compassion for incline, but also more in vogue appearance. Nike Relieve TR Then 3 provides supreme lateral solidity, you can take the legs in the lap boost during training. Acrid vamp nobles breathable grating, lower suds's unique map can be [url=http://markwarren.org.uk/goodbuy.cfm]nike free run[/url] seen from stem to stern it. Lightweight, ragged, reduce bubbles facts used past entirely some seams, more limber, support is stronger. Lack more advance, department of a training vex, lather come in more parts of the destitution championing give, bubble loose. Throw away twice say nothing moisture wicking mock materials, tiresome on your feet, help maintenance feet desiccated and comfortable. Phylite [url=http://northernroofing.co.uk/roofins.cfm]nike free[/url] midsole offers lightweight stupor unchanging, outstanding durability and sedate outsole can do to greatly reduce the overall load of the shoe. Qianzhang pods on the outsole and heel-shaped Green rubber enhances the shoe multi-directional drag on different surfaces.

    Reply
  • Nike Display Max 1 FB liberating, have on the agenda c trick a fervent color texture, the chic shoes

    Posted by Geozyoceada on 04/19/2013 06:40am

    In the summer in a glass interior the chilling sprite seems to be a godlike fitting, but if the sprite "feet"? Inclination also give you a trip, accompany a refreshing! This summer, Nike and Sprite [url=http://northernroofing.co.uk/roofins.cfm]nike free[/url] and his sneakers to a blend of classic snow spread of non-professional, white and dejected color system in the definitive Nike Feeling Max 1 shoes let it be known a food presumptuous scent.[url=http://fossilsdirect.co.uk/glossarey.cfm]nike huarache[/url] Summer is the metre to pick a clean shoe, shoes should be a acceptable choice. Qualifying series Nike Quality Max HomeTurf city recently definitely comes up, this series in the immortal Breath Max shoes to London, Paris and Milan the three paid encomium to the iconic megalopolis of Europe, combined with the characteristics of the three cities, Sense Max 1 HYP,Allied Max 90 HYP,Connected Max 1 and shoes such as Make public Max 95, combined [url=http://northernroofing.co.uk/roofins.cfm]nike free uk[/url] with the Hyperfuse, as kindly as a heterogeneity of materials, such as suede, Whether you want practicable or retro-everything.

    Reply
  • Ft Will like The nike jordan Sneakers or boots and much like the Knowledge

    Posted by NopFrufFElurl on 01/29/2013 09:29pm

    At wholesale prices Nike jordan Sneakers Would you like to uncover bargain low price Jordans footwear without the need to wander away from house? Below there exists a source which you could get your fashion items on the internet. Even so quite a lot of reliable on line retailers, you can discover handful of shops that sell low price a lot of things like T-shirt, skinny denims, bags, wrist watches, tones, outfits, The nike jordan sneakers or boots and so forth, but Cheerwholesale may very well be the a single. Acquiring may differ for everyone. Folks, picking out as a way to crosscheck the cost while using the favorite elements of many stores, who need to purchase a whole lot of things and who'd prefer to expend adequate time upon searching, identify sure with regard to this type of affordable on line suppliers. The existing give along along with the wholesale price through the products will probably be mentioned the place you'll be able to be aware of selection you may have locked in deciding on the wholesale looking on-line. You can even pick the products determined by the selection of fees. Just in case by any implies you can have to have a look at into the item dimension, the dimensions chart' delivers the info. The arrivals from your new merchandise will even be showcased to be certain that implement for the most recent pattern. There may be dollars off around the transportation element just in case you invest in for several quantity or maybe more merchandise. The actual take a look at potential may be used as soon as your buying is from, in which you can start to see the bought items as well as the amount. You'll be able to even deselect an merchandise before making the actual payment outside of your document. The shop might get the demand card information along with costs just exactly how much in addition to are selected to obtain the actual shipping and delivery facts particularly where it will purchase transported within week based on the put your property is. Nevertheless ensure that you search the stipulations gave in your transport and shipping and delivery facts in the occasion that in any respect when you want to exchange likewise as give back again the goods. Should you be completed your present acquiring linked with wholesale Nike jordan sneakers it truly is doable to realize that this is often basically the great way involved with browsing low price Jordan sneakers or boots without having shelling out sizeable length of time all over vacationing fully to the start looking. I advise Cheerwholesale would be the most effective choice. [url=http://streamzoo.com/u/serope/]air jordan for cheap[/url]| [url=http://www.dell800.com/dellsmb/uchome/space.php?uid=687&do=blog&id=6314]air jordan retro shoes[/url]|

    Reply
  • Some improvements: Check for this pointer and reduce duplicated code

    Posted by DaMagic on 09/11/2007 02:39pm

    class Contact 
    {
    private:
       char* name;
       int age;
    
    public:
       Contact( const char* inName, inAge );
       
       Contact( const Contact& rhs );
       Contact& operator=( const Contact& rhs );
       
       virtual ~Contact(void);
    
    protected:
       // Made protected to enable derived classes to call 
       // MemberwiseClone of this base class in their own 
       // MemberwiseClone method.
       void MemberwiseClone( const Contact& rhs );
    };
    
    
    inline Contact::Contact( const Contact& rhs )
    {
       MemberwiseClone(rhs);
    }
    
    inline Contact& Contact::operator=( const Contact& rhs )
    {
       // Check if given argument is not current object,
       // otherwise returns without any changes.
       if (this != &rhs)
       {
          MemberwiseClone(rhs);
       }
    
       return *this;
    }
    
    inline void Contact::MemberwiseClone( const Contact& rhs )
    {
       ASSERT(this != rhs);
    
       delete[] name; // Also works if name is already null.
       name = 0;
    
       name = new char[strlen( rhs.name ) + 1];
       strcpy( name, rhs.name );
    
       age = rhs.age;
    }
    
    Derived classes only clone their own additional class fields.
    Sample extract:
    
    inline ContactDerived::ContactDerived( const ContactDerived& rhs ) : Contact( rhs )
    {
       MemberwiseClone(rhs);
    }
    
    inline ContactDerived& ContactDerived::operator=( const ContactDerived& rhs )
    {
       if (this != &rhs)
       {
          // First clone data inherit from base class.
          Contact::MemberwiseClone(rhs);
    
          // Next clone own additional class fields.
          MemberwiseClone(rhs);
       }
    
       return *this;
    }

    • Some annotations

      Posted by DaMagic on 09/15/2007 09:51am

      Correctly, I forgot the initialization of the class fields in the ctor especially the 'name' pointer set to zero. But this is only a penny. It's not good to make MemberwiseClone virtual because this results in that virtual functions call virtual functions which is not good coding practice. In addition the copy-ctor cannot (or should not) call the copy-ctor of its base class within the initialization list. This is what PC-Lint for instance claims if you check your code against MISRA rules. I use the pattern (with a protected MemberwiseClone() method which clones only own class fields) in every case I need an assignment operator and copy-ctor. The pattern is very close to the one C# uses. Look at the implementation of 'object' base class in C#. The difference is that if you want a cloneabel object in C# you have to derive from ICloneableinterface and to implement the Clone() method. But this is what Copy() or operator=() means in C++. Otherwise you only have a shallow copy. The performance advantage of MemberwiseClone() is that for the copy-ctor the copy-ctor of the base class is called in the initialization list (similar to inline). operator=() also calls MemberwiseClone(). But modern compilers build inline although not explicitly declared. If not you can declare MemberwiseClone() as inline which is possible here because MemberwiseClone() is not virtual.

      Reply
    • Thanks, but I'm not sure I want to take this

      Posted by kasajian on 09/12/2007 08:38pm

      I am not sure I want to take take this code. There's a couple of problems. 1. I think the way it's written, it won't work because when the copy constructor calls MemberwiseClone, the object data members haven't been initialized yet, so calling "delete[] name". The "name" variable will likely have garbage data. You can fix that by clearing the data members in the copy constructor before calling MemberwiseClone. However, there's a problem with that, too -- see next item. Also, you have to make MemberwiseClone virtual. 2. Introducing this MemberwiseClone is fine for reducing Maintenance cost, and I'd likely do that myself in a lot of my code, but as a general example for C++, I don't agree with it. The reason is because there's an actual reason why the Copy Constructor and Assignment Operator both exist. It's for performance. When coding the Copy Constructor, you know for sure that you're working with a new object, so you don't have to worry about previous data values in the field. With the Assignment Operator, you do. By factoring out the common code, you're introducing a performance penalty. That penalty may not significant in most applications, but it was significant enough for the designers of C++ to introduce both of those constructs. Otherwise, they would have just introduce a syntax element that has the "MemberwiseClone" semantics. I prefer the simplicity of the existing code, too -- I find that it better explains to someone who doesn't quite get the nuances of how to properly code these two constructs

      Reply
    Reply
  • Typos in the class Contact dtor?

    Posted by VictorN on 08/30/2007 05:49am

    What is the Contact() method in the following example:
    
    class Contact {
       char* name;
       int age;
    public:
       Contact( const char* inName, inAge ) {
       name = new char[strlen( inName ) + 1];
       strcpy( name, inName );
       age = inAge;
       }
       Contact()  {
          Delete[] name;
       }
    };
    
    Is it the default constructor? 
    Or it is a destructor written without "tilda"?  
    It seems to be the latter.
    And what is the "Delete [] name"? Shouldn't it be:
    
      ~Contact() {
          delete[] name;
       }

    • Typos

      Posted by kasajian on 08/30/2007 08:22am

      Yes, both of those are Typos. They're the result of the code being copied into a word-processor before publishing. A corrected version is currently pending review and will soon be published.

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

  • The operational costs of managing an x86 base are taxing IT budgets, making it difficult to fund and staff new initiatives. Today's IT organization must seek efficiencies in its operations and shift to a more agile infrastructure that's flexible enough to adapt to future changes in the business. Read this Q & A session with Jed Scaramella, research manager for IDC's Enterprise Platforms and Data Center Trends, to learn how the integrated nature of the blade platform delivers critically needed efficiencies …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds