部分引用:https://blog.youkuaiyun.com/liitdar/article/details/81874541
对象赋值
如同基本类型的赋值语句一样,同一个类的对象之间也是可以进行赋值操作的,即将一个对象的值赋给另一个对象。
对于类对象的赋值,只会对类中的数据成员进行赋值,而不对成员函数赋值。
给对象赋值和调用拷贝构造函数初始化另一个对象行为是类似的,但是有所区别,下面会讲到(实际上调用的是拷贝构造函数)
拷贝构造函数和赋值
拷贝构造函数和赋值运算符的行为比较相似,都是将一个对象的值复制给另一个对象;但是其结果却有些不同,拷贝构造函数使用传入对象的值生成一个新的对象的实例,而***赋值运算符是将对象的值复制给一个已经存在的实例。***这种区别从两者的名字也可以很轻易的分辨出来,拷贝构造函数也是一种构造函数,那么它的功能就是创建一个新的对象实例;赋值运算符是执行某种运算,将一个对象的值复制给另一个对象(已经存在的)。
调用的是拷贝构造函数还是赋值运算符,主要是看是否有新的对象实例产生。如果产生了新的对象实例,那调用的就是拷贝构造函数;如果没有,那就是对已有的对象赋值,调用的是赋值运算符。
以下代码用于辨析何时使用了拷贝构造、何时使用了赋值运算符
复制
使用拷贝构造函数操作对象的方式,称为“对象的复制”。
int main()
{
Person p;
Person p1 = p; // 1
Person p2;
p2 = p; // 2
f(p2); // 3
p2 = f1(); // 4
Person p3 = f1(); // 5
getchar();
return 0;
}
1、使用对象 p创建了一个新的对象p1,毫无疑问使用的是拷贝构造函数
2、p2这个对象已经提前声明好了,执行的仅仅只是将p的值复制给p2
3、这个就是拷贝构造函数 调用时机 之一“对象以值传递的方式传入函数参数”
4、这条语句拷贝构造函数和赋值运算符都调用了。函数f1以值的方式返回一个Person对象,在返回时会调用拷贝构造函数创建一个临时对象tmp作为返回值;返回后调用赋值运算符将临时对象tmp赋值给p2
5、直接调用拷贝构造函数使用f1()返回值创建了对象p3
特别要说的是
- 对象进行赋值时,两个对象必须属于同一个类;
- s2 = s1; 只会使得学生2和学生1的各项数据相同,但是学生还是两个独立的个体;
- 对象赋值是通过赋值运算函数实现的\
- 在对象声明之后,进行的对象赋值运算,才属于“真正的”对象赋值运算,即使用了赋值运算符“=”;而在对象初始化时,针对对象进行的赋值操作,其实是属于对象的复制。
//就是说 通过一个对象创建了另一个对象 调用的是拷贝构造函数(strcpy函数),执行的是复制操作
Person p;
Person p1 = p; // 1
//对象全部创建好之后,执行的"=" 才算是赋值操作
ClassA obj1;
ClassA obj2;
obj2 = obj1; // 此语句为对象的赋值
赋值操作中内存变化
int main()
{
ClassA obj1(1, "liitdar");
ClassA obj2;
return 0;
}
上述中,声明了对象obj1和obj2之后,系统将会为其分配相应大小的内存空间(由于obj1初始化了,所以空间中存放的是liitdar 但是obj2并没初始化,所以存的是随机值)
注:图片来源https://blog.youkuaiyun.com/liitdar/article/details/81874541
执行赋值操作后 obj2 = obj2; 会将对象中的所有位于 stack 中的域进行相应的复制操作;
目前就到这个程度,望指正。