我们知道,当我们我们没有定义赋值操作符时,编译器会生成一个默认的赋值操作符执行浅拷贝,就像默认构造函数一样是编译器默认生成的。而如果勒种有引用就需要注意一个大大的误区。我们知道引用在定义的时候就需要初始化,指定这个引用变量是哪个变量的别名,否则就会报错。当一个类中使用了引用但没有定义赋值操作符,会导致什么问题呢?
#include<iostream>
using namespace std;
class Test
{
int x;
int &ref;
public:
Test (int i):x(i), ref(x) {} //有参构造,引用看似是赋初始值了
void print() { cout << ref; }
void setX(int i) { x = i; }
};
int main()
{
Test t1(10);
Test t2(20);
t2 = t1;
t1.setX(40);
t2.print();
return 0;
}
上面的程序会编译报错:
Compiler Error: non-static reference member 'int& Test::ref', can't use default assignment operator
意思就是非静态的引用成员,’int& Test::ref’,不能使用默认的赋值运算符。
那么这里为什么不能使用默认的赋值运算符呢?其实C++中是有规定的,在下面的这些情况下,编译器不会自动创建默认赋值操作符:
1. 类中包含const或volatile类型的非静态数据成员
2. 类中包含一个非静态的数据成员,并且其类型是不能赋值的(例如引用)。
3. 被继承的基类中不能使用赋值操作符(例如基类中包含引用类型的成员)。
只要上面的某个条件成立,则用户必须自定义赋值操作符。所以我们需要修改上面的程序,增加一个赋值运算符的重载就可以了。
#include<iostream>
using namespace std;
class Test
{
int x;
int &ref;
public:
Test (int i):x(i), ref(x) {} //有了赋值运算符才可以直接赋值
void print() { cout << ref; }
void setX(int i) { x = i; }
Test &operator = (const Test &t) { x = t.x; return *this; } // 重载赋值运算符
};
int main()
{
Test t1(10);
Test t2(20);
t2 = t1;
t1.setX(40);
t2.print();
return 0;
}
输出: 10