一个类如果我们没有自己定义构造函数和拷贝构造函数以及赋值函数(赋值运算符)的话,编译器会自动加入这三个函数的默认函数。同时拷贝时是浅拷贝。
深拷贝和浅拷贝不懂的可以参考一下我另一篇博客:
深拷贝和浅拷贝详解
首先我们要了解一下这三种名词的区别:
-
构造函数
构造函数是用来创建一个对象的时候的调用的函数,构造函数可以重载,也就是一 个类可以包含多个构造函数只要每两个构造函数的形参不相同即可。 -
拷贝构造函数
拷贝构造函数也属于构造函数的一种,同样是在创建一个对象的时候会调用,只不过是用另一个对象来创建一个新的对象。 -
赋值运算符(=)
赋值运算符是在将一个对象赋值(=)给另一个对象的时候调用的函数。
其次我们通过例子了解一下具体的函数形式以及调用情况。(拷贝构造函数有一些特殊的调用情况)
class A {
public:
int a;
public:
A()
{
a = 2;
}
A(int i) {
this->a = i;
}
};
int main()
{
A a();
A a1(5);
}
上述代码中,第5行和第10行即为类A的两种构造函数,这里就体现了构造函数是可以重载的,但是要保证参数是不相同的。在创建对象的时候,可以根据自己的需要选择不同的构造函数,如:17和18行即是分别调用两种不同的构造函数。
class A {
public:
int a;
public:
A()
{
a = 2;
}
A(int i) {
this->a = i;
}
A(const A& b)//拷贝构造函数
{
this->a = b.a;
}
};
int main()
{
A a();
A a1(5);
A a2(a);
A a3=a1;
}
上图中第14行即为拷贝构造函数的定义形式,而其调用则是在第24行:用一个已经创建的对象来创建另一个对象。
看第25行,猜猜看这里调用的是赋值函数(=)还是拷贝构造函数?
答案是拷贝构造函数;这里虽然用了赋值运算符,但是由于a3一开始并不存在,到这里才刚刚要创建,所以编译器就自动选择调用了拷贝构造函数,参数即为=后面的a1。
class A {
public:
int a;
public:
A()
{
a = 2;
}
A(int i) {
this->a = i;
}
A(const A& b)//拷贝构造函数
{
this->a = b.a;
}
A& operator=(const A& c)//赋值运算符重写
{
a= c.a;
return *this;
}
};
int main()
{
A a();
A a1(5);
A a2(a);
A a3=a1;
a2=a3;
}
第18行即是赋值运算符的定义形式,同时其调用为第31行,前面介绍拷贝构造函数已经讲过了第30行调用的是拷贝构造函数,第31行调用的才是赋值函数(即赋值运算符)。
最后讲一下:如果一个类没有定义拷贝构造函数,同时类的成员变量中包含其他类的对象,那么这个类进行拷贝构造的时候会默认调用成员变量的拷贝构造函数;如果定义了拷贝构造函数,则会按照函数的内容执行,不会自动调用其成员变量的拷贝构造函数。
同理,赋值运算符也是如上所述。
本篇到此为止,转载请标明出处。