1、对已经存在的对象的赋值
#include "iostream"
using namespace std;
class A {
public:
A(int a) :_a(a)
{
cout << "A(int a)" << endl;
}
A(const A& a) {
cout << "A(const A& a)" << endl;
_a = a._a;
}
A& operator=(const A& a) {
cout << "operator=(const A& a)" << endl;
if (&a != this) {
_a = a._a;
return *this;
}
}
public:
int _a;
};
int main() {
A a1(1);
A a2(2);
a1 = 10;
return 0;
}
// 输出:
//A(int a)
//A(int a)
//A(int a)
//operator=(const A& a)
会先用 10 进行构造一个匿名对象,然后调用赋值重载对已经存在的a1进行赋值。
2、对不存在的对象赋值进行构造
先看一个现象:
#include "iostream"
using namespace std;
class A {
public:
A(int a) :_a(a)
{
cout << "A(int a)" << endl;
}
A(const A& a) {
cout << "A(const A& a)" << endl;
_a = a._a;
}
A& operator=(const A& a) {
cout << "operator=(const A& a)" << endl;
if (&a != this) {
_a = a._a;
return *this;
}
}
public:
int _a;
};
int main() {
A a1 = A(2);
return 0;
}
//输出:
//A(int a)
按道理是先构造了一个匿名对象,然后再对 a1 调用拷贝构造来构造对象,但是这里很明显编译器优化了,直接进行一次构造。
因此 main 中改成:
int main() {
A a1 = 10;
return 0;
}
得到的结果与上面一致,只调用一次的构造函数。因为这里也是先利用10 构造一个匿名函数,然后进行拷贝构造。
当然上述的操作在加了explicit后都不可以了
禁止隐式类型转换,禁止的是一个操作数在进行运算符操作时,利用构造函数升级成这个类
比如,上述10,在与A这个类型的对象进行运算符操作时,通过构造函数升级成A类型的匿名对象