在C++中,类的特殊成员函数是指那些由编译器自动生成的函数,它们在特定情况下会被调用,以支持类的某些操作。这些特殊成员函数包括:
-
默认构造函数(Default Constructor):
- 当没有提供任何构造函数时,编译器会自动生成一个默认构造函数。
- 它不接受任何参数,或者所有参数都有默认值。
- 如果类中定义了其他构造函数,编译器不会自动生成默认构造函数。
-
复制构造函数(Copy Constructor):
- 当一个对象作为另一个对象的副本时,编译器会调用复制构造函数。
- 它接受一个同类型的对象的引用作为参数。
- 如果类中定义了复制构造函数,编译器不会自动生成默认的复制构造函数。
-
赋值运算符(Assignment Operator):
- 当使用赋值操作符(
=
)将一个对象赋值给另一个对象时,编译器会调用赋值运算符。 - 它接受一个同类型的对象的引用作为参数。
- 如果类中定义了赋值运算符,编译器不会自动生成默认的赋值运算符。
- 当使用赋值操作符(
-
移动构造函数(Move Constructor):
- 当一个对象通过移动语义(使用右值引用)被创建时,编译器会调用移动构造函数。
- 它接受一个右值引用作为参数。
- 如果类中定义了移动构造函数,编译器不会自动生成默认的移动构造函数。
-
移动赋值运算符(Move Assignment Operator):
- 当一个对象通过移动语义被赋值时,编译器会调用移动赋值运算符。
- 它接受一个右值引用作为参数。
- 如果类中定义了移动赋值运算符,编译器不会自动生成默认的移动赋值运算符。
-
析构函数(Destructor):
- 当对象生命周期结束时,编译器会调用析构函数。
- 它没有参数,也不返回任何值。
- 如果类中定义了析构函数,编译器不会自动生成默认的析构函数。
这些特殊成员函数对于类的正确使用至关重要,因为它们确保了类的资源管理(如内存分配和释放)能够正确执行。在设计类时,应该根据类的需要来决定是否需要自定义这些特殊成员函数。如果类中包含动态分配的资源(如指针、文件句柄等),通常需要自定义析构函数来释放这些资源,以避免内存泄漏。同样,如果类需要支持复制或移动操作,也应该提供相应的特殊成员函数。
#include <iostream>
class MyClass {
public:
// 默认构造函数
MyClass() {
std::cout << "Default constructor called." << std::endl;
}
// 复制构造函数
MyClass(const MyClass& other) {
std::cout << "Copy constructor called." << std::endl;
// 深拷贝或浅拷贝逻辑
if (other.m_ptr) {
auto n = std::strlen(other.m_ptr) + 1;
m_ptr = new char[n];
std::memcpy(m_ptr, other.m_ptr, n);
}
}
// 赋值运算符
MyClass& operator=(const MyClass& other) {
std::cout << "Co py assignment operator called." << std::endl;
// 赋值逻辑
if (this != &other)
delete[] m_ptr; // 释放已经存在的资源
if(other.m_ptr != nullptr){
auto n = std::strlen(other.m_ptr) + 1;
m_ptr = new char[n];
std::memcpy(m_ptr, other.m_ptr, n);
}
return *this;
}
// 移动构造函数 -- 新建对象,不需要const
MyClass(MyClass&& other) noexcept {
std::cout << "Move constructor called." << std::endl;
// 移动逻辑
if (other.m_ptr)
m_ptr = std::move(other.m_ptr)
other.m_ptr = nullptr;
}
// 移动赋值运算符 -- 对已有的对象进行赋值,不需要const
MyClass& operator=(MyClass&& other) noexcept {
std::cout << "Move assignment operator called." << std::endl;
// 移动赋值逻辑
if (this != &other) {
delete[] m_ptr; //释放已存在的资源
}
if (other.mtr)
m_ptr = std::move(other.m_ptr);
other.m_ptr = nullptr;
return *this;
}
// 析构函数
~MyClass() {
std::cout << "Destructor called." << std::endl;
if (m_ptr)
delete[] m_ptr;
}
private:
char *m_ptr;
};
int main() {
// 使用默认构造函数创建对象
MyClass obj1;
// 使用复制构造函数创建对象
MyClass obj2(obj1);
// 使用赋值运算符
MyClass obj3;
obj3 = obj2;
// 使用移动构造函数创建对象
MyClass obj4(std::move(obj1));
// 使用移动赋值运算符
MyClass obj5;
obj5 = std::move(obj4);
return 0;
}