问答题 复制构造函数与赋值运算符的区别是什么
【正确答案】
【答案解析】复制构造函数是一种特殊的构造函数,在生成一个实例的时候,一般会同时生成一个默认的复制构造函数,复制构造函数完成一些基于同一类的其他对象的构建及初始化工作。具体而言,复制构造函数有如下特点:
1)该函数名与类同名,因为它也是一种构造函数,并且该函数不指定返回类型。
2)该函数只有一个参数,并且是对某个对象的引用。
3)每个类都必须有一个复制构造函数。
4)如果程序员没有显式地定义一个复制构造函数,那么,C++编译器会自动生成一个缺省的复制构造函数。
5)复制构造函数的目的是建立一个新的对象实体,所以一定要保证新创建的对象有独立的内存空间,而不是与先前的对象共用。
虽然说在生成实例时会同时生成一个默认的复制构造函数,但是在定义一些类时,有时需要甚至强烈推荐显式地定义复制构造函数用来实现特定的用户操作。
而赋值操作符则不一样,它用已存在的对象来创建另一个对象,给对象赋予一个新的值,由于赋予的是新值,反过来说,该对象原来就有值,所以赋值函数只能被已经存在了的对象调用,而不能凭空产生。而且如果不主动编写复制构造函数和赋值函数,编译器将以“位复制”的方式自动生成默认的函数,如果类中含有指针变量,那么这两个默认的函数就隐含了错误。
具体而言,复制构造函数相比较赋值运算法有以下3个方面的不同:
①复制构造函数生成新的类对象,而赋值运算符不能。
②由于复制构造函数是直接构造一个新的类对象,所以在初始化这个对象之前不用检验源对象是否和新建对象相同。而赋值运算符则需要这个操作,另外赋值运算中如果原来的对象中有内存分配,要先把内存释放掉。
③当类中有指针类型的成员变量时,一定要重写复制构造函数和赋值构造函数,不能使用默认的。
简单点说,当进行一个类的实例初始化时,也就是构造时,调用的是构造函数,但如是用其他实例来初始化,则调用复制构造函数,非初始化时对这个实例进行赋值调用的是赋值运算符。
程序示例如下:
#include<iostream>
using namespace std;
class CTest
{
public:
int m_muber;
CTest():m_muber(0)
{
cout<<"CTest()<<endl;
}
CTest(const CTest&t)
{
cout<<"CTest(const CTest&t)"<<endl;
this->m_muber=t.m_muber;
}
CTest(const int&t)
{
cout<<"CTest(const int&t)"<<endl;
this->m_muber=t;
}
CTest& operator=(const CTest&t)
{
cout<<"CTest& operator=(const CTest&t)"<<endl;
this->m_muber=t.m_muber;
return *this;
}
CTest& operator=(const int&t)
{
cout<<"CTest& operator=(const int& t)"<<endl;
this->m_muber=t;
return *this;
};
int main()
{
cout<<"CTest a: ";
CTest a;
cout<<"CTest b(a): ";
CTest b(a);
cout<<"CTest c=a : ";
CTest c=a;
cout<<"CTest d=5 : ";
CTest d=5;
cout<<"b=a : ";
b=a;
cout<<"c=5 : ";
c=5;
return 0;
}
程序输出结果:
CTest a: CTest()
CTest b(a):CTest(const CTest& t)
CTest c=a : CTest(const CTest& t)
CTest d=5 : CTest(const int& t)
b=a : CTest& operator=(const CTest& t
c=5 : CTest& operator=(const int& t)