讨论/《C++ 面试突击》 - 为什么拷贝构造函数必须为引用?/
《C++ 面试突击》 - 为什么拷贝构造函数必须为引用?
共 4 个回复

相当于 ex1 作为函数 A(const A tmp)的形参,在参数传递时相当于 A tmp = ex1

这里面 ex1 是形参??? ex1是实参,tmp 才是形参吧,付费的资料都这么不靠谱啊?

playground下的运行结果:

#include <iostream>
using namespace std;

class A
{
private:
    int val;

public:
    A(int tmp) : val(tmp) // 带参数构造函数
    {
        cout << "A(int tmp)" << endl;
    }

    A(const A &tmp) // 拷贝构造函数
    {
        cout << "A(const A &tmp)" << endl;
        val = tmp.val;
    }

    A &operator=(const A &tmp) // 赋值函数(赋值运算符重载)
    {
        cout << "A &operator=(const A &tmp)" << endl;
        val = tmp.val;
        return *this;
    }

    void fun(A tmp)
    {
    }
};

int main()
{
    A ex1(1); //A(int tmp)
    A ex2(2); //A(int tmp)
    cout<<endl;
    //1.新建对象并赋值为已有对象 拷贝初始化 因实现方式而不同!
    A ex3 = ex1; //A(const A &tmp) 拷贝构造函数
    cout<<endl;
    //2.给已有对象赋值
    ex2 = ex1; //A &operator=(const A &tmp) 赋值函数
    cout<<endl;
    //3.调用包含非引用非指针的A类型形参的函数
    ex2.fun(ex1); //A(const A &tmp) 拷贝构造函数
    cout<<endl;
    //4.新建对象并赋值为"类型名(int)"  因实现方式而不同!
    A ex4=A(4); // A(int tmp) 构造函数
    cout<<endl;
    //5.新建对象并用已有对象初始化 直接初始化 
    A ex5(ex1); //A(const A &tmp) 拷贝构造函数
    cout<<endl;
    //6.new一个对象,传参为该类的已有对象
    A *ex6=new A(ex1); //A(const A &tmp) 拷贝构造函数
    cout<<endl;
    //7.new一个对象,传参为int
    A *ex7=new A(7); //A(int tmp) 构造函数
    return 0;
}
/*
运行结果:
A(int tmp)
A(int tmp)

A(const A &tmp)

A &operator=(const A &tmp)

A(const A &tmp)

A(int tmp)

A(const A &tmp)

A(const A &tmp)

A(int tmp)
*/

以下情况会调用拷贝构造函数

1.直接初始化和拷贝初始化时
string dots("zhang"); //直接初始化
string dots = "zhang" //拷贝初始化

2.将一个对象作为实参传递给一个非引用或非指针类型的形参时

3.从一个返回类型为非引用或非指针的函数返回一个对象时

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

何时调用复制构造函数
新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。这在很多情况下都可能发生,最常见的情况是新对象显式地初始化为现有的对象。例如,假设motto是一个StringBad对象,则下面4种声明都将调用复制构造函数:
StringBad ditto(motto);
StringBad metoo = motto;
StringBad also = StringBad(motto);

StringBad * pStringBad = new StringBad(motto);
其中中间的2种声明可能会使用复制构造函数直接创建metoo和also,也可能使用复制构造函数生成一个临时对象,然后将临时对象的内容赋给metoo和also,这取决于具体的实现。最后一种声明使用motto初始化一个匿名对象,并将新对象的地址赋给pStringBad指针。

链接:https://www.zhihu.com/question/30726582/answer/49192393
来源:知乎

不传入引用只能做到浅拷贝,并且传参过程种还会有拷贝和析构的开销