默认构造函数将作为参数传入的对象的每个成员变量复制到新对象的成员变量中,这被称为成员浅复制。这虽然对大多数成员变量可行,但对于指向自由存储区中对象的指针成员变量不可行。
成员浅复制只是将对象成员变量的值复制到另一个对象中,两个成员变量的指针最后指向同一个内存块,当其中任何一个指针被delete时,将生成一个迷途指针,程序将处于危险之中。如图:
假如旧对象指针成员变量所指堆内存被释放后,此时新对象指针成员变量仍指向该内存块,这是不合法的。这种情况的解决办法是:创建自己的复制构造函数并根据需要来分配内存。分配内存后,可以将原对象的值复制到新内存中。这称之为深层复制。
程序实例如下:
- #include <iostream>
- using namespace std;
- class Cat
- {
- public:
- Cat();
- Cat(const Cat &);
- ~Cat();
- int GetAge() const { return *itsAge; }
- int GetWeight() const { return *itsWeight; }
- void SetAge(int age) { *itsAge=age; }
- private:
- int *itsAge; //实际编程并不会这样做,
- int *itsWeight; //我仅仅为了示范
- };
- Cat::Cat()
- {/*构造函数,在堆中分配内存*/
- itsAge=new int;
- itsWeight=new int;
- *itsAge=5;
- *itsWeight=9;
- }
- Cat::Cat(const Cat & rhs)
- {/*copy constructor,实现深层复制*/
- itsAge=new int;
- itsWeight=new int;
- *itsAge=rhs.GetAge();
- *itsWeight=rhs.GetWeight();
- }
- Cat::~Cat()
- {
- delete itsAge;
- itsAge=0;
- delete itsWeight;
- itsWeight=0;
- }
- int main()
- {
- Cat Frisky;
- cout << "Frisky's age: "<<Frisky.GetAge()<<endl;
- cout << "Setting Frisky to 6.../n";
- Frisky.SetAge(6);
- cout << "Create Boots from Frisky/n";
- Cat Boots=Frisky; //or Cat Boots(Frisky);
- cout << "Frisky's age: " <<Frisky.GetAge()<<endl;
- cout << "Boots' age : "<<Boots.GetAge()<<endl;
- cout << "Set Frisky to 7.../n";
- Frisky.SetAge(7);
- cout << "Frisky's age: "<<Frisky.GetAge()<<endl;
- cout << "Boots' age: "<<Boots.GetAge()<<endl;
- return 0;
- }
- //输出:
- //Frisky's age: 5
- //Setting Frisky to 6...
- //Create Boots from Frisky
- //Frisky's age: 6
- //Boots' age : 6
- //Set Frisky to 7...
- //Frisky's age: 7
- //Boots' age: 6