一、对象的等同操作
在实际工程开发中,经常遇到类似于下面的问题:
int a;
a = 1;
int b = 0;
b = a;
int c = a;
举这么简单的例子可能大家觉得有点LOW,但是,假如把上面的原生类型改成类对象,会是什么现象呢?
这也就引出了今天的问题。在类中有拷贝构造函数,有=赋值重载函数,那么这二者在什么情况下会调用呢?换成比较通俗的问题,如果想让两个对象保持一致,应该怎么做。也就是像上面简单例子中 b = a,c = a之类的操作。
二、分析
应该说这是一个相当基础的问题,但可能许多人虽然心里知道是怎么回事儿,但在使用的时候儿跟别人讲总是讲不太清楚,其实说白了,还是自己没有从根本上了解清楚,其中就有一个是“拷贝构造函数和等赋值重载区别”的问题,或者说,类对象的声明和定义的细微区别之处,在这里就体现的很明显。
同学在学习编程时就会听到这样一种话,变量的声明和定义,那他们到底有什么不同呢?其实好多人是会用不知道。特别是在类对象的声明和定义上,到底有什么不同呢?同学们可以考虑静态变量,这个就扯远了,这里不深入说。
还是老样子,先看代码:
class CopyEqual
{
public:
CopyEqual() { std::cout <"this is construct" <std::endl; }
~CopyEqual() {}
CopyEqual(const CopyEqual& ce)
{
std::cout <"this is copy" <std::endl;
}
public:
CopyEqual & operator= (const CopyEqual& ce)
{
std::cout <"this is =" <std::endl;
return * this;
}
private:
int num = 0;
int ref = 1;
};
int main(){
CopyEqual ce; //1
CopyEqual ceCopy(ce); //2
CopyEqual cEqual = ce; //3
CopyEqual copye = CopyEqual(); //4
CopyEqual cEq; //5
cEq = ce; //6
cEq = CopyEqual(); //7
return 0;
}
大家运行一下,有疑问下断点调试一下就明白了,其实这也没有什么难度,就看对基础掌握的扎实程程度了。普通构造函数的使用,在经典的书籍中提到过有三种等价方式(为构造函数指定实参有三种等价形式),即:
// 一般等价的形式
A a1( "first" );
A a2 = A( "second" );
A a3 = "third";
a3 的形式只能被用于指定单个实参的情形 对于两个以上的实参 只能使用 a1 和a2 的形式 一般来说应该推荐使用 a1 的形式
// 推荐的构造函数形式
A a1( "first" );
对照上面贴的代码,大家明白了吧。1和4其实是一样的。同样,2和3也是一样的,同时调用拷贝构造函数,只不过2更让大家看上去象是一个拷贝构造函数。
5声明后然后进行6、7,就会调用=赋值操作运算符重载。
换句话说,操作运算符重载,是在对已经存在的一个对象用另外一个对象进行赋值时会调用。而如果是在声明和定义同时进行时,如3,就会调用拷贝构造函数而不是=操作运算符重载的函数。
而6和7表明,左值才会是声明定义,右值嘛也不是啊。
这些细节,需要在实际使用上小心应对,不可大意。
三、总结
c++之所以让大家感到有难度,学习曲线不如其它语言明显,主要就在于其中有大量类似于这些基础的知识点需要学习,而且一旦这些基础掌握不好,可能就会对程序的运行产生歧义,导致在实际工程中,思想和目标走了两条路。费尽了心思和精神,最后才恍然大悟,就是这么一个简单的知识点。
侯捷书中有一句话:“勿在浮沙筑高台”。