C++:类的六个默认函数之一 —— 拷贝构造函数


概念

我们在创建对象时,可否创建一个与一个对象一模一样的新对象呢?

拷贝构造函数只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

特征

拷贝构造函数也是特殊的成员函数,其特征如下:

  1. 拷贝构造函数是构造函数的一个重载形式
  2. 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。

无穷调用具体来说:

当一个对象以值方式传递时,编译器会生成代码调用它的拷贝构造函数生成一个复本。如果类A的拷贝构造函数是以值方式传递一个类A对象作为参数的话,当需要调用类A的拷贝构造函数时,是以值方式传进一个A的对象作为实参; 而以值方式传递需要调用类A的拷贝构造函数;结果就是调用类A的拷贝构造函数导致又一次调用类A的拷贝构造函数,这就是一个无限递归。

拷贝构造函数能不能用指针作为参数?

代码不会报错,可以正确输出。但是这并不是一个拷贝构造函数了,拷贝构造函数的参数必须是引用类型的才可以。所以说用指针作为参数,这其实是一个构造函数,参数类型为A*

class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
private:
    int _year;
    int _month;
    int _day; 
};

int main() {
    Date d1;
    Date d2(d1);
	return 0; 
}
以传值方式传参数:

在这里插入图片描述

  1. 若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做 浅拷贝,或者值拷贝。
class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    } 
private:
    int _year;
    int _month;
    int _day;
};
int main() {
    Date d1;
    // 这里d2调用的默认拷贝构造完成拷贝,d2和d1的值也是一样的。
    Date d2(d1);
    return 0; 
}

实现一个String类(深、浅拷贝)

要点总结:
  • 拷贝构造函数指的是参数为本类其他对象的引用的构造函数,他在给对象初始化成本类其他对象时调用。系统会自动提供一个拷贝构造函数。

知识点习题

  1. 下列情况中,不会调用拷贝构造函数的是()。

A.用一个对象去初始化同一类的另一个新对象时
B.将类的一个对象赋值给该类的另一个对象时
C.函数的形参是类的对象,调用函数进行形参和实参结合时
D.函数的返回值是类的对象,函数执行返回调用时

正确答案:

B

答案解析:

拷贝构造函数调用的时机:

  1. 当用类的一个对象初始化该类的另一个对象时
  2. 如果函数的形参是类的对象,调用函数时,进行形参和实参结合时.
  3. 如果函数的返回值是类的对象,函数执行完成返回调用者时.
  4. 需要产生一个临时类对象时(B选项调用的是赋值运算符重载)

  1. 以下代码共调用多少次拷贝构造函数:
Widget f(Widget u)
{  
   Widget v(u);
   Widget w=v;
   return w;
}
main(){
    Widget x;
    Widget y=f(f(x));
}

A. 1
B. 3
C. 5
D. 7

正确答案

D

答案解析

在实例化类对象a时调用的是构造函数,然后将

  1. 实参与形参结合时会调用一次拷贝构造函数;
  2. 初始化局部变量时调用一次拷贝构造函数;
  3. 给局部变量赋值时调用一次(初始化的时候赋值调用的是拷贝构造函数);
  4. 函数返回并与形参进行结合时再调用一次。所以第一次调用func()函数时调用了4次。
  5. 在此调用时不需要再将实参与形参结合(第一个f 的返回值直接作为第二个f 的参数,这是编译器优化)
  6. 直接初始化调用一次,赋值调用一次,函数返回赋值给调用一次。所以第二次调用func()函数时调用了3次。

如果有不同见解,欢迎留言讨论!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值