在C++中,拷贝构造函数和赋值运算符重载(assignment operator overload)都是用于处理对象之间的复制操作,但它们之间存在一些重要的区别。
拷贝构造函数
拷贝构造函数是一种特殊的构造函数,它用于创建一个新的对象作为现有对象的副本。其形式如下:
cpp复制代码
className(const className &obj); |
其中,className
是类名,&obj
是对现有对象的引用。拷贝构造函数在以下情况下被调用:
- 当用一个对象去初始化另一个同类型的对象时。
- 当函数参数是类的对象,调用函数进行传值时。
- 当函数的返回值是类的对象时。
例如:
cpp复制代码
class MyClass { | |
public: | |
int x; | |
MyClass(int val) : x(val) {} // 构造函数 | |
MyClass(const MyClass &obj) : x(obj.x) {} // 拷贝构造函数 | |
}; | |
int main() { | |
MyClass obj1(10); // 调用构造函数 | |
MyClass obj2 = obj1; // 调用拷贝构造函数 | |
return 0; | |
} |
赋值运算符重载
赋值运算符 =
可以被重载以定义自定义类型的对象赋值操作。形式如下:
cpp复制代码
className &operator=(const className &obj); |
这个运算符通常用于将一个对象的值赋给另一个已经存在的对象。它返回一个对调用对象的引用,这允许连续赋值操作。
例如:
cpp复制代码
class MyClass { | |
public: | |
int x; | |
MyClass(int val) : x(val) {} // 构造函数 | |
MyClass &operator=(const MyClass &obj) { // 赋值运算符重载 | |
if (this != &obj) { // 防止自赋值 | |
x = obj.x; | |
} | |
return *this; | |
} | |
}; | |
int main() { | |
MyClass obj1(10); | |
MyClass obj2; | |
obj2 = obj1; // 调用赋值运算符重载 | |
return 0; | |
} |
拷贝构造函数与赋值运算符重载的区别
- 目的不同:拷贝构造函数用于创建一个新的对象作为现有对象的副本,而赋值运算符重载用于将一个对象的值赋给另一个已经存在的对象。
- 返回值不同:拷贝构造函数没有返回值(它构造一个对象并返回该对象的引用),而赋值运算符重载返回一个对调用对象的引用。
- 参数不同:拷贝构造函数的参数是一个对现有对象的常量引用,而赋值运算符重载的参数也是一个对现有对象的常量引用,但它还隐含地接收调用对象(即 *this)作为左侧操作数。
- 处理对象状态不同:拷贝构造函数创建新对象时,可以安全地假设对象处于有效但未初始化的状态。然而,赋值运算符重载必须假设调用对象已处于有效状态,并且在赋值期间需要维护这种状态。这就是为什么在赋值运算符重载中通常需要检查自赋值(即赋值给自己)的情况,以避免潜在的问题。
- 调用时机不同:拷贝构造函数在创建新对象时被调用,而赋值运算符重载在已经存在的对象被赋予新值时被调用。