2012年2月15日 星期三

Copy Constructor Notes


Why write a copy constructor? The compiler will provide one for you. Why bother, do you really need more practice writing constructors? The answer depends on your class. The compiler provided copy constructor performs a "shallow copy".  This means that each data member is "cloned" for the new copy. For example, consider this class:

class X {
int        a;
double        b;
char        c[10];

};

X    Object1;
X    Object2(Object1);        // this uses the copy ctor

The compiler provided copy constructor would copy each of Object1's members to Object2, so two object would be identical. In this case, you do not need to write a copy constructor.

What about this class?

class Y {

char*    ptr;

};

Y    Object3;
Y    Object4(Object3);        // this uses the copy ctor

Again, the compiler provided copy constructor would perform a shallow copy. This means that Object4's ptr would contain the same address as Object3's ptr. Is that what you want? This means that if you change the value that ptr points to for Object 3, then you also changed it for Object 4. Hence, the two objects and not autonomous. So, you should write a copy constructor in this case, so that ptr points to its own value. The typical copy constructor for this case should look something like this:

Y::Y(const Y& _Y) {

  ptr = new char[strlen(_Y.ptr)+1];
  strcpy(ptr,_Y.ptr);

}


Example 4-13 – This should demonstrate why you might want to write a copy constructor.

1      // File: ex4-13.cpp - Why write a copy constructor?
2     
3      #include <iostream>
4     
5      class ABC
6      {
7          int * p;
8      public:
9              ABC(int P=0) { p = new int(P); }
10              ~ABC() { delete p; }
11              int value() const { return *p; }
12      };
13     
14      void print (ABC object)
15      {
16          std::cout << object.value() << std:: endl;
17      }
18     
19      int main()
20      {
21          ABC x(2);
22          print (x);
23          ABC y(3);
24          print(y);
25          print (x);
26      }


******  Output  ******

Microsoft Visual C++ 2008

2
3
-572662307
!!!!!!  Runtime error  !!!!!!


gnu g++ compiler, version 4.3.2 on Linux

2
3
0
Program crash!!!!!

Note: the gnu c++ compiler has an option to compile with warnings that violate the style guidelines for Scott Meyers' Effective C++ book, -Weffc++. This option would have produced the following warnings:

/home/joe/deanza/examples> g++ ex4-13.cpp -Wall -Weffc++
ex4-13.cpp:6: warning: `class ABC' has pointer data members
ex4-13.cpp:6: warning:   but does not override `ABC(const ABC&)'
ex4-13.cpp:6: warning:   or `operator=(const ABC&)'
ex4-13.cpp: In constructor `ABC::ABC(int)':
ex4-13.cpp:9: warning: `ABC::p' should be initialized in the member initialization list


What should the signature of a copy constructor look like?

class Cls
{

Cls(Cls cls);        // 1. argument passed by value?
Cls(Cls& cls);         // 2. argument passed by reference?
Cls(const Cls& cls);     // 3. argument passed by reference to const?

};

  1. won't work.  If it did, it would be an infinitely recursive call.
  2. Works, but it's not as "safe" as 3.  (do you know why?)
  3. This is the best. You may not have 2 and 3 present together.

沒有留言:

張貼留言