C++拷贝构造函数总结

目录:

  1. 拷贝构造函数的基础知识
  2. 拷贝构造函数的使用
  3. 拷贝构造函数的行为

 

1.拷贝构造函数的基础知识

拷贝构造函数(copy constructor)是构造函数,是拷贝已经存在的对象来创建一个新的对象。此方法的声明形式:object(const object&)。

例如:

class Object
{
    Object(const Object &);
};

注意:参数的传递是引用传递的。因为如果在此处使用值传递,会造成递归引用。

 

2.拷贝构造函数的使用

拷贝构造函数在什么时候被使用,有助于我们了解拷贝构造函数的用途。一般而言,拷贝构造函数会在以下三种情况下被使用:

    1. 当构造一个新的对象时
    2. 使用值传递来传递函数参数
    3. 函数的返回值

2.1.当构造一个新的对象时,例如:

1 class Object{…};
2 Object a;
3 Object b = a;// 此函数调用的是拷贝构造函数
4 Object c;
5 c = a;          // 此处调用的是"operator = “

2.2.使用值传递来传递函数参数,例如:

1 class Object{…};
2 int Function_A(Ojbect param);
3 Object a;
4 Function_A(a);//在调用Function_A的时候,在函数内部使用a的拷贝构造函数来获取a的副本来进行函数的处理。

2.3.函数的返回值,例如:

1  class Object{…};
2   
3  Object GetObject()
4  { 
5      Object a; 
6       return a;
7  }

 

 

3.拷贝构造函数的行为

拷贝构造函数分为默认构造函数和用户自定义函数,在此主要由这两方面来说明:

a. 默认构造函数:

如果对象没有提供显式的拷贝构造函数,编译器在发现需要使用拷贝构造函数函数的时候,会生成一个来使用,而生成的拷贝构造函数会有trival和nontrival之分,区别在于对象是否应该被按位拷贝(bitwise copy semantics)。

首先说下按位拷贝,首先来看下下面的代码:

1 #incluude “word.h”
2 
3 Word d(“abcd”);
4  
5 void fun() 
6 { 
7     Word verb = d;
8 }

我们得知,verb是根据d来初始化的,但是如果无法看到Word的定义,我们无法知道Word的默认构造函数的行为。如果Word中的成员变量都是内建类型的,例如,Word的定义如下:

 1 Class Word
 2 { 
 3 public:
 4    Word(const char *);
 5    ~Word(){delete []m_pData;}
 6  //
 7 private: 
 8     char *m_pData; 
 9     int m_iSize;
10 };

 

那么,Word的定义呈现了“default copy semantics”,verb的初始化直接按位拷贝,编译器不用生成默认构造函数。但是,如果Word的成员变量中有成员变量声明了显式的拷贝构造函数,那么编译器就需要合成构造函数来完成verb的初始化操作,例如:

 

 1 #include<string>
 2 Class Word
 3 {
 4 public:
 5     Word(const char*); 
 6     ~Word(){delete []m_pData} 
 7     //
 8     private: 
 9     std::string m_strData; 
10     int m_iSize; 
11 };

 

在此情况下,我们知道string声明有显式的拷贝构造函数,编译器在初始化verb的时候,就需要合成一个拷贝构造函数来调用string的拷贝构造函数。在合成的拷贝构造函数中,整型,指针等nonclass member也都会被拷贝。

需要注意的是,在以下的四种情况是不需要进行按位拷贝的:

    • class内部的成员变量声明有显式的拷贝构造函数(不论是定义者声明(例如string)还是编译器合成的(例如包含string的Word定义))。
    • class的基类有显式的拷贝构造函数(无论是被声明的还是被合成的)。
    • class中有虚函数,因为编译器需要为对象设置虚函数表,所以无法按位拷贝。
    • class继承虚基类。

b.用户自定义拷贝构造函数

顾名思义,是用户自己定义的拷贝构造函数,编译器发现由用户定义的拷贝构造函数的时候,是不会生成拷贝构造函数的。即使用户声明的构造函数有错误。但是在使用自定义构造函数的时候需要注意几点:

1.注意深拷贝和浅拷贝,在前面的例子中不含string的Word的定义中,有一个char *的指针,如果不考虑深拷贝,直接按位赋值的话,会造成隐含的bug。

2.在构造函数中不要调用虚函数,因为在此时对象没有创建完成,不能保证调用到正确的函数,同时,也会引起其他的错误(例如,类内部的成员变量没有初始化完毕就是用)。

3.在拷贝构造函数中需要考虑异常的发生。

 

以上就是拷贝构造函数的总结。其中第2,3节的示例来自《深入了解C++对象模型》。

如果有不对的地方,请大家指正,谢谢。

yetuweiba

posted @ 2013-10-27 14:59  yetuweiba  阅读(1649)  评论(2编辑  收藏  举报