为什么C++中的拷贝构造函数的形参不能使用值或者指针传递?

1、先说结论:

(1)如果使用值传递的话,那么调用拷贝构造函数的时候,首先需要将实参传递给形参,这个传递的时候又要调用拷贝构造函数,这样就会造成无限递归,最后发生栈溢出,但事实上编译器在语法检查上就已经是禁止这种行为的。

(2)如果使用指针传递,这样定义的构造函数实际是一个自定义的有参构造函数,而并非拷贝构造。拷贝构造函数只有一个,如果自定义了拷贝构造函数,编译器直接调用自定义的拷贝构造,否则编译器会自动合成一个。

2、拷贝构造函数被调用的场景有哪些?

(1)用=定义变量时会调用拷贝构造

(2)将一个对象作为实参传递给一个非引用类型的形参

(3)从一个返回类型为非引用类型的函数返回一个对象

(4)用花括号列表初始化一个数组中的元素或者一个聚合类中的成员

3、下面用代码去验证一下:

情况1:(定义一个指针类型的构造函数)

#include<iostream>
using namespace std;
class A
{
public:
    A(int a){this->m_a = a;cout<<"call A(int)"<<endl;}
    A(const A*tmp){this->m_a = tmp->m_a;cout<<"call A(const A*)"<<endl;}
    int get(){return m_a;}
    
private:
    int m_a;
};
​
A fun1(A a)
{
    cout<<a.get()<<endl;
    return a;
}
// 测试A(const A*tmp)有没有调用成功
void test1()
{
    cout<<"---------THIS IS TEST1--------"<<endl;
    A a(2);
    A b(&a);
}
​
// 测试发生拷贝构造的场景会不会调用A(const A*tmp)
void test2()
{
    cout<<"---------THIS IS TEST2--------"<<endl;
    A a(5);
    A b = a;
    fun1(b);
}
​
int main()
{
    test1();
    test2();
    return 0;
}
/*
    输出结果:
    ---------THIS IS TEST1--------
    call A(int)
    call A(const A*)
    ---------THIS IS TEST2--------
    call A(int)
    5
*/

        由上面可见,我们定义一个指针类型的构造函数,但是无论在=定义变量的场景,还是在fun1中使用非引用类型的形参以及非引用类型的实参都没有调用A(const A* tmp)这个构造函数,所以A(const A* tmp)仅仅只是一个自定义的有参构造,并不是拷贝构造。

情况2:(定义一个引用类型的构造函数)

#include<iostream>
using namespace std;
class A
{
public:
    A(int a){this->m_a = a;cout<<"call A(int)"<<endl;}
    A(const A&tmp){this->m_a = tmp.m_a;cout<<"call A(const A&)"<<endl;}
    int get(){return m_a;}
    
private:
    int m_a;
};
​
A fun1(A a)
{
    cout<<a.get()<<endl;
    return a;
}
​
int main()
{
    A a(5);
    A b = a;
    fun1(b);
    return 0;
}
/*
    输出结果:
    call A(int)       // A a(5)
    call A(const A&)  // A b = a
    call A(const A&)  // 调用fun1时实参拷贝到形参
    5                 // cout<<a.get()<<endl
    call A(const A&)  // 调用fun1时返回值为非引用类型时发生的拷贝
*/

        显然,自定义的A(const A&tmp)才是真正的拷贝构造函数,因为所有会发生拷贝构造的场景都调用了A(const A&tmp)。让我们来回归拷贝构造函数的定义:如果一个构造函数的第一个参数时自身类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造(《C++ Primer》(第五版) P440 )。

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

czy1219

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值