拷贝构造函数(copy constructer),析构函数(destructer)和赋值运算符(assignment operator)(的重载)组成了拷贝控制(copy control)。
拷贝构造函数,通常只有一个参数,本类类型的
const引用,用于:
1.显式或隐式的用已有对象的值来初始化一个新的对象。
2.复制一个对象,当作实参传递给函数。
3.复制一个对象作为函数参数的返回值。
4.用于初始化顺序容器的元素。
5.根据元素初始化列表初始化数组中的元素。
拷贝构造函数
should 使用初始化列表的方式进行成员"复制"。
string s("section13");//通过string类的构造函数直接给新对象s赋值
string s="section13";//先创建一个临时string对象,把section13赋值给它,再通过拷贝构造函数把临时对象的值赋值给s。
此两种方法导致的机器底层语言优化不同。
IO类型的对象不能用拷贝构造函数赋值。
非引用类型的函数参数与非引用类型的函数返回值都是复制后的。(如果是类类型的,就是调用了拷贝构造函数)
顺序容器的初始化中,vector
vec[5],先创建一个临时对象,之后调用5次拷贝构造函数。
注:为了优化通常创建一个空的顺序容器,然后向其中加入想要的值,当然想用容器初始化后默认的值时例外。
当创建类类型的数组时,如果没有为类类型的数组提供元素初始化形式,调用的是默认构造函数;如果用常规的括号列表进行初始化,则调用的是拷贝构造函数。
这也就解释了在《c++学习笔记2-顺序容器的操作》中不解的地方。
#include <iostream>
using namespace std;
class s12{
public:
s12():i(2){
cout<<"in s12 constructor\n";
}
s12(s12 &obj){
cout<<"in s12 copy constructor\n";
}
~s12(){
cout<<"in s12 destructor\n";
}
int i;
};
int func(s12 argu)
//s12 func(s12& argu)
{
cout<<"argu.i:: "<<argu.i<<endl;
}
//s12 func2();
int main(void) {
//puts("Hello World!!!");
s12 obj_s12;
cout<<"obj_s12.i:: "<<obj_s12.i<<endl;
s12 obj2=obj_s12;
//obj_s12.~s12();
cout<<"obj2.i:: "<<obj2.i<<endl;
cout<<"in func\n";
func(obj_s12);
cout<<"end func\n";
return EXIT_SUCCESS;
} |
运行结果1为
in s12 constructor
obj_s12.i:: 2
in s12 copy constructor
obj2.i:: 2293600
in func
in s12 copy constructor
argu.i:: 29953184
in s12 destructor
end func
in s12 destructor
in s12 destructor |
首先注意到在我们自己定义了拷贝构造函数后,通过“=”给obj2初始化赋值,调用的是定义的考构,在其中只有一条输出语句而无实际的复制,故obj_s12的i值并没有复制给obj2,obj2的i值是2293600,随机的。
在函数func中,形参为类s12类型的对象,不是引用,所以要对参数进行复制,再当作实参传进函数,故输出中在in func的下面看到了考构,在函数结束end func的上面看到将创建的临时对象析构。
我们将函数定义处改为传引用,其它不变。
输出结果2为
in s12 constructor
obj_s12.i:: 2
in s12 copy constructor
obj2.i:: 2293600
in func
argu.i:: 2
end func
in s12 destructor
in s12 destructor |
函数执行时就没有了对形参的复制。
我们再将函数改为
s12 func(s12& argu)
{
cout<<"argu.i:: "<<argu.i<<endl;
return argu;
} |
运行结果3为
in s12 constructor
obj_s12.i:: 2
in s12 copy constructor
obj2.i:: 2293600
in func
argu.i:: 2
in s12 copy constructor
in s12 destructor
end func
in s12 destructor
in s12 destructor |
结果3与结果1不同在于结果3在函数体内输出argu.i后看到考构,因为此时函数的返回值是s12类型对象,非引用,需要调用考构创建一个临时对象将其返回。
如果将函数返回值改为s12 &,返回的是引用,则输出结果与结果2相同,函数内没有考构出现。
阅读(668) | 评论(0) | 转发(0) |