——复制构造函数用于将一个对象的值复制到新创建的对象中,用于初始化过程中(包括按值传递参数),而不是常规的赋值过程中

原型:

Class_name(const Class_name &)

  

何时调用:

  • 新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用
StringBad ditto(motto);    // calls StringBad(const StringBad &)
StringBad metoo = motto;    // calls StringBad(const StringBad &)
StringBad also = StringBad(motto);    // calls StringBad(const StringBad &)
StringBad * pStringBad = new StringBad(motto)    // calls StringBad(const StringBad &)

  中间两种声明可能会使用复制构造函数直接创建metoo和also,也可能使用复制构造函数生成一个临时对象,然后将临时对象的内容赋给metoo和also,这取决于具体的实现

  • 每当生成了对象副本时,编译器都将使用复制构造函数。具体地说按值传递和返回对象时,都将调用复制构造函数(按值传递意味着创建原始变量的一个副本)。
  • 由于按值传递对象时将调用复制构造函数,因此应该按引用传递对象。这样可以节省调用构造函数的时间以及存储新对象的空间

功能:

——默认的复制构造函数逐个复制非静态成员(成员复制也称为浅复制),复制的是成员的值

StringBad sailor = sports;

//等效于

StringBad sailor;
sailor.str = sports.str;
sailor.len = sports.len;

  只是由于私有成员是无法访问的,因此后面的代码不能通过编译

静态对象不受影响,因为它们属于整个类,而不是各个对象

默认复制构造函数的问题:

一:

默认的复制构造函数不说明其行为(全盘复制),如果需要在构造函数中修改类静态数据成员,这时就会发生错误

解决办法:提供一个显示复制构造函数

StringBad::StringBad(const String &s)
{
    num_strings++;    // static int num_strings声明在类中
    ... // imported stuff to go here
}

  

如果类中包含这样的静态数据成员,即其值将在新对象被创建时发生变化,则应该提供一个显示复制构造函数

二:

隐式复制构造函数的浅复制(复制指针)导致的内存问题

  • 新对象可能修改指针指向的内存
  • 新对象若走完生命周期将会调用析构函数释放指针指向的内存,但当原对象也调用析构函数时,由于该段内存已被释放,这将导致不确定的、可能有害的结果,另一个症状是试图释放内存两次可能导致程序异常终止

解决办法:定义一个显示复制构造函数,进行深度复制

StringBad::StringBad(const StringBad &st)
{
    num_strings++;    // handle static member update
    len = st.len;    // same length
    str = new char [len + 1];    // allot space
    std::strcpy(str, st.str);    // copy string to new location
    ...
}

  复制字符串并将副本的地址赋给str成员

如果类中包含了使用new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针,这被称为深度复制。复制的另一种形式(成员复制或浅复制)只是复制指针值。浅复制仅浅浅地复制指针信息,而不会深入“挖掘”以复制指针引用地结构

 

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/suui90/p/13126933.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!

相关课程