注:以下为阅读网络上以及书上的相关内容后,自己总结的结果。因参考资料众多,无法附上链接,在此抱歉。
一个类A,如果什么都不编写,c++编译器将自动为A产生四个默认的函数(实际上还有两个,在此不列出),即:
函数 | 名称 |
---|---|
A(void) | 1、默认无参数构造函数 |
A(const A &a) | 2、默认拷贝构造函数 |
~A(void); | 3、默认的析构函数 |
A & operator = (const A &a); | 4、默认的赋值函数 |
对于构造函数和析构函数我们都了解。那么拷贝构造函数和赋值函数是什么呢?
一、基本概念
1、拷贝构造函数:(也叫复制构造函数)
拷贝构造函数是C++独有的,它是一种特殊的构造函数,简单地说,是用来初始化另一个类对象的函数。
当没有重载拷贝构造函数时,即没有在类里面重写拷贝构造函数时,通过默认拷贝构造函数来创建一个对象:
class A {
public:
A(A& x) // 第一种形式
A(const A& x) // 第二种形式
A(A& x, int a = 0, int b = 1…) // 第三种形式
};
A a;
A b(a); // 这里b对象还没有存在,是用 a 对象来构造和初始化 b 的!
// 第一种写法
A b=a; // 第二种写法
2、赋值函数:
当一个类的对象向该类的另一个对象赋值时,就会用到该类的赋值函数。
当没有重载赋值函数时,通过默认赋值函数来进行赋值操作:
(赋值函数本质是赋值操作符,重载赋值函数即重写赋值操作符)
class A {
//……
};
A a;
A b; // 这里b对象是已经存在的,是用 a 对象来赋值给 b 的!
b=a;
二、为何要自己重写
既然系统能自动生成这些函数,为什么还需要自定义?
最重要的原因是:默认的拷贝构造函数 和 默认的赋值函数 均采用 位拷贝 而非 值拷贝。
位拷贝 拷贝的是地址,而 值拷贝 拷贝的是内容。
位拷贝 == 浅拷贝 == 按位拷贝
值拷贝==深拷贝 == 按值拷贝
浅拷贝会发生的问题:
- a原来的内存区域未释放,造成内存泄露。
- a和b指向同一块区域,任何一方改变,会影响到另一方。
- 当对象释放时,b会释放掉两次。
因此:当类中还有指针变量时,拷贝构造函数 和 赋值函数 就隐含了错误。此时需要自己定义。
具体解释网上有一位解释的非常好,找时间把地址贴过来。
不理解也没关系,只要记住一件事就好:必须要重写!
如果不想写拷贝构造函数和赋值函数,又不允许别人使用编译器生成的默认的函数,最简单的办法是将拷贝构造函数和赋值函数声明为私有函数:
class A
{
private:
A(const A& a); // 私有拷贝构造函数
A& operate=(const A& a); // 私有赋值函数
}
三、什么情况下使用
什么情况用到拷贝构造函数:
1)一个对象以值传递的方式传入函数体
2)一个对象以值传递的方式从函数返回
3)一个对象需要通过另一个对象进行初始化
class A {
public:
A(A& x) // 第一种形式
};
int Fun1(A x)
{
return x.a + x.b;
}
A Fun2(int a, int b)
{
A a(a, b);
return a;
}
A c(10, 10);
A d(c); // 情况1) -> 调用拷贝构造函数
int e = Fun1(c); // 情况2) -> 调用拷贝构造函数
A f = Fun2(11, 11); // 情况3) -> 调用拷贝构造函数
P.S.
赋值函数需要处理自我赋值的问题,因为自我赋值会出现指针指向一个已经释放的内存。(详见最后一个链接的文章)
例子:
String::String(const String &other)
{
cout << "自定义拷贝构造函数" << endl;
int length = strlen(other.m_data);
m_data = new char[length + 1];
strcpy(m_data, other.m_data);
}
String & String::operator=(const String &other)
{
cout << "自定义赋值函数" << endl;
if (this == &other) //※
{
return *this;
}
else
{
delete [] m_data;
int length = strlen(other.m_data);
m_data = new char[length + 1];
strcpy(m_data, other.m_data);
return *this;
}
}
四、文章推荐
几篇我认为对我帮助很大的好文章:
C++类中拷贝构造函数详解
C++中构造函数,拷贝构造函数和赋值函数的区别和实现
对于拷贝构造函数和赋值构造函数的理解
复制构造函数 与 赋值函数 的区别
C++赋值函数详解