C++ 小菜2:拷贝构造函数

来源:互联网 发布:c语言考研知识点总结 编辑:程序博客网 时间:2024/05/18 04:55

拷贝构造函数(copy constructor)是一种特殊的构造函数,用于拷贝一个已存在的实例。

当一个新变量通过另一个对象创建,即在声明时初始化,拷贝函数将会被调用。符合该要求的情况如下:

Person q("Mickey"); // constructoris used to build q.

Person r(p);         //copy constructor is used to build

r. Person p = q;    // copy constructor is used to initialize in declaration.

p = q;                // Assignment operator, no constructor or copy constructor.

注意,赋值操作并不会调用拷贝构造函数。除它以外,以上几种情况拷贝构造函数都会调用。如果你没有在类中定义拷贝构造函数,C++将会调用默认的拷贝构造函数。注意,默认拷贝构造函数的拷贝过程属于浅拷贝(shallow copy)。关于浅拷贝,稍后我会详解。


根据C++的标准,如果要定义一个拷贝构造函数,必须按照以下四种标准,择一编写:

1. MyClass( const MyClass& other );   

2. MyClass( MyClass& other );   

3. MyClass( volatile const MyClass& other );   

4. MyClass( volatile MyClass& other );

注意,以下几种都不是正规写法:

1.  MyClass( MyClass  *other );

2. MyClass( const MyClass  *other );

3.  MyClass( MyClass  other );

如果你仅需要浅拷贝(shallowcopy),就无需自行编写拷贝构造函数。与之对应,如果需要深拷贝(deep copy),那么就必须编写拷贝构造函数了。

在此,我先来解析浅拷贝和深拷贝的区别。


浅拷贝(shallow copy):

以B拷贝A的内容为例。浅拷贝的过程中,B只拷贝A的域值( field value)。如果A的域值是一个内存地址,那么,拷贝完成后,A、B指向同一个地址。即A、B共享一个元素。


深拷贝(deep copy)

深拷贝则是复制所有的内容。即把A指向地址包含的内容,全部复制给B,B仍指向之前的地址,但是该地址的内容与A地址包含的内容相同。


简言之,浅拷贝复制了指针深拷贝复制了指针内容

浅拷贝的缺点在于,如果你修改了B指向地址的内容,A指向的内容同时也会被修改。深拷贝拷贝的缺点在于拷贝过程费时、费空间。


如果你因为要进行深拷贝而自行编写了拷贝构造函数,那么你同时需要编写析构函数以及重载赋值运算符。

下面是一个拷贝构造函数的例子:

class MyClass 

{

     int x;

     char c;

     std::string s;   

};

MyClass::MyClass( const MyClass& other ) : x( other.x ), c( other.c ), s( other.s )   {}

这里强调一下为何构造函数的参数使用了const。使用const 可以保证拷贝构造函数不会修改传入的引用。但如果参数是 non-const,那么参数不能是临时对象( temporary object)。临时对象,就是没有变量名的对象实例。

以下述代码为例:

// Improperly declared function:  parameter should be const reference:   

 void print_me_bad( std::string& s ) 

{

       std::cout << s << std::endl;   

}    

// Properly declared function: function has no intent to modify s:   

void print_me_good(const std::string& s ) 

{

       std::cout << s << std::endl;   

}

std::string hello( "Hello" );

print_me_bad( hello ); // Compiles ok; hello is not a temporary   

print_me_bad( std::string( "World" ) ); // Compile error; temporary object   

print_me_bad( "!" );           // Compile error; compiler wants to construct temporary std::string from const char*   

 

print_me_good( hello );  // Compiles ok   

print_me_good( std::string( "World" ) );  // Compiles ok   

print_me_good( "!" );      // Compiles ok 

因为print_me_bad没有使用const参数,所以无法向它传入临时对象。

原创粉丝点击