了解完拷贝构造函数的调用时机,我们再来看看编译器生成的默认拷贝构造函数都做了什么。默认拷贝构造函数主要作用是按位拷贝,在必要的时候,除了按位拷贝,还插入一些其他行为,具体内容请看先前的文章----[C++拷贝构造函数总结](http://www.cnblogs.com/yetuweiba/p/3390853.html)。在实现拷贝构造函数中我们需要注意一点深拷贝和浅拷贝,防止出现的拷贝不完全的错误。
  以上是构造函数的语法基础知识点,根据上面的原理,可以总结出来一些容易出错的地方,具体请看下面。
  >1.如果对象拥有成员变量,需要在自定义构造函数中设定初值,尽可能地使用成员初始化列表对成员变量进行初始化。同时,成员变量是按照声明的顺序来构造的,所以,要注意依赖。
  在构造函数中对成员变量进行初始化的话,在编译器中实际上是先调用此成员变量的构造函数,再调用它的赋值函数,所以,使用成员初始化列表会节省效率。
  成员变量的构造是按照声明的顺序进行的,所以,不要让声明早的成员变量依赖声明晚的成员变量。示例如下

 

class Obj
{
private:
int a;
int b;
// 下面的构造函数是错误的
Obj(const int value)
: a(b + 1)    // error,此时b还未构造好,a的值会不可预料。
, b(value) // 正确的做法是调换a和b的声明顺序,在成员初始话列表中也调换a和b的顺序
{}
};

  >2.谨慎在构造函数中调用虚函数(好不要在构造函数中调用虚函数)。
  我们先来举一个例子:

 

class Base
{
Base()
{
fun();//error,此时调用的是Base的fun,会发生调用错误。
}
virtual void fun() = 0;
};
class Derivate : public Base
{
Derivate(){};
virtual void fun()
{
std::cout << "I am Derivate" << std::endl;
}
};
Derivate d;

  上面代码中,构造d会发生错误,因为基类早于派生类进行构造,在基类构造的时候,是不会下降到派生类中的,也是此时只会调用基类的函数,而Base中的fun是存虚函数,此时会发生错误。虽然我们可以在Derivate的构造函数中调用fun,但这样做,意味着接口的设计出现了问题。所以,好不要在构造函数中调用虚函数。
  >3.在并发环境下,注意构造函数的安全性。
  当在并发的环境下,原本简单的事情会变的复杂。我们都知道,在并发环境下,线程的执行是乱序的,我们拿到一个指向对象的指针,这个指针指向的可能是构造函数执行一般的对象,例如:
  class Foo : public Observer
  {
  // error
  Foo(Observable * s)
  {
  s->register(this)
  }
  }
  上面例子的做法是不安全的,因为在构造函数中将自身注册出去,此时对象可能仍未完全构造完。如果,Foo是积累的话,那么注册的时候派生类还没有构造完成,此时也会引发错误。所以,由上例可知:在对象构造期间不要对外暴露this指针(陈硕)。解决上面错误的一个方法是“二段式构造”,即对象构造完成后,再对外暴露this指针。
  以上是关于C++中构造函数的一些总结,如果有错误的地方,请大家多多指教,谢谢。另外,不支持Markdown,有些不方便。