目录
默认拷贝构造函数
拷贝构造函数的原型:
为什么不用值传递?
为什么不用指针传递?
调用拷贝构造函数的3种情况 (旧对象去构造新对象)
我们熟悉的类型有以下操作:
1.声明:int a;
2.声明并初始化:int a = 10;
3.赋值:int a = 10;int b = a;
类作为一个类型当然也有以上操作,其中默认的构造函数可以完成操作1,人为建立的构造函数可以完成操作2,3。对于第三种操作,类中也提供了默认的函数——拷贝构造函数。
默认拷贝构造函数
类会提供一个默认的拷贝构造函数,用已有对象的值去依此初始化新对象的值;如果人为提供了,则类不会提供默认。
拷贝构造函数又叫复制构造函数。
拷贝构造函数的原型:
类名(const 类名& 形参名) :(初始化列表){}
可以看到,这里是引用传递,加了const防止值被修改
为什么不用值传递?
值传递将待传的值赋值一份过去,形参需要初始化,如果使用值传递,像下面这样,程序会掉入死循环:
假如有:A a = 10;A b(a);
将a传入成员b时调用拷贝构造函数A(A t);
而A(A t)函数中的形参成员t需要初始化,这又需要调用拷贝构造函数A(A t);
如此下去不断调用拷贝构造函数,无穷无尽。
class A
{
public:A(int i = 0) :m_i(i) { cout << "A" << m_i << endl; }~A() { cout << "~A" << m_i << endl; }A(A t) :m_i(t->m_i)//值传递{cout << "A(A)" << endl;}void print() { cout << m_i << endl; }
private:int m_i;
};
为什么不用指针传递?
A(A* t) :m_i(t->m_i)
{cout << "A(A)" << endl;}
其实指针传递的结果是对的,但是看的时候有歧义
A a = 10;A b = &a;//人们无法确定是用a初始化b,还是用&a初始化b;A b(&a)的作用同A b = &a
调用拷贝构造函数的3种情况 (旧对象去构造新对象)
1.用已有对象去初始化新对象
2.函数传参--值传递 由实参传递给形参的过程
3.函数返回值 --类类型的值返回,由局部对象构造临时对象
情况1很好理解
A a(5); //A(int) 5
A b(a);//用a去初始化b对象
情况2就是拷贝构造函数为什么不用值传递的原因
void fun(A t){}
情况3在const关键字那篇中提到过,函数传参时不是把本身的变量传过去,而是生成一个临时存储空间,这个临时的空间如果是类类型的则需要调用拷贝构造函数。
A fun(){}
最后看一下这些函数的调用:
class A
{
public:A(int i = 0) :m_i(i) { cout << "A" << m_i << endl; }~A() { cout << "~A" << m_i << endl; }A(const A& t) :m_i(t.m_i) //拷贝构造函数{cout << "A(A)" << m_i << endl;}void print() { cout << m_i << endl; }
private:int m_i;
};
void fn(A s) //A s(c) 用c构造s 调用拷贝构造 A(A) 30
{cout << "fn" << endl;//fn在即将退出的时候,要将局部对象s析构 ~A 30
}
A test()
{A tt(60); //A 60return tt; //从tt到临时对象调用拷贝构造
} void main()
{A a(5); A b(a); A c(30); //调用普通构造 A 30fn(c);c = test();
}
结果: