下面我将详细讲解一下C++中特殊成员函数的相关知识。
一起聊聊C++中的特殊成员函数
什么是特殊成员函数
在C++中,除了一些普通的成员函数,还有一些被称为特殊成员函数的成员函数。这些特殊成员函数包括:
- 默认构造函数
- 拷贝构造函数
- 移动构造函数
- 拷贝赋值运算符
- 移动赋值运算符
- 析构函数
这些函数被称为特殊成员函数的原因是它们都在特定的情况下被自动调用,无需显式调用。
默认构造函数
默认构造函数是一种没有参数的构造函数,它在创建对象时被自动调用,用来初始化对象的成员变量。如果我们没有定义默认构造函数,那么编译器会为我们自动生成一个默认构造函数。
class MyClass {
public:
MyClass() {
// 构造函数的实现
}
};
需要注意的是,如果我们在类中定义了其他构造函数,那么编译器就不会为我们生成默认构造函数,这时如果我们需要默认构造函数,就需要显式地定义它。
也可以把默认构造函数定义为被删除的函数,这样编译器在需要默认构造函数时就不能自动生成。
class MyClass {
public:
MyClass() = delete;
};
拷贝构造函数
拷贝构造函数是一种特殊的构造函数,用来在创建新对象时,将一个已有的对象的值赋值给新对象。拷贝构造函数的参数为该类的另一个对象的引用。
class MyClass {
public:
MyClass(const MyClass& other) {
// 拷贝构造函数的实现
}
};
需要注意的是,如果我们不定义拷贝构造函数,编译器会为我们自动生成一个默认的拷贝构造函数,该函数会对类的每个成员变量执行浅拷贝操作。如果我们的类中有指针类型的成员变量,就需要显式定义拷贝构造函数,以执行深拷贝操作。
class MyClass {
public:
MyClass(const MyClass& other) {
this->p = new int(*other.p); // 深拷贝
}
private:
int* p;
};
移动构造函数
移动构造函数也是一种特殊的构造函数,它在创建新对象时使用一个临时对象的值,避免了拷贝操作,提高了程序的效率。移动构造函数的参数为一个右值引用。
class MyClass {
public:
MyClass(MyClass&& other) {
// 移动构造函数的实现
}
};
需要注意的是,如果我们不定义移动构造函数,编译器会为我们自动生成一个默认的移动构造函数,该函数会对类的每个成员变量执行浅拷贝操作。如果我们的类中有指针类型的成员变量,就需要显式定义移动构造函数,以执行浅拷贝操作。
class MyClass {
public:
MyClass(MyClass&& other) {
// 移动构造函数的实现
this->p = other.p; // 浅拷贝
other.p = nullptr;
}
private:
int* p;
};
拷贝赋值运算符
拷贝赋值运算符用来在已经存在的对象之间赋值。拷贝赋值运算符的参数为该类的另一个对象的引用。在实现拷贝赋值运算符时,需要注意要进行自我赋值的判断。
class MyClass {
public:
MyClass& operator=(const MyClass& other) {
// 拷贝赋值运算符的实现
if (this == &other) { // 自我赋值
return *this;
}
delete this->p; // 释放原有的内存
this->p = new int(*other.p); // 深拷贝
return *this;
}
private:
int* p;
};
移动赋值运算符
移动赋值运算符也是在已经存在的对象之间赋值,它使用一个临时对象的值,避免了拷贝操作,提高了程序的效率。移动赋值运算符的参数为一个右值引用。
class MyClass {
public:
MyClass& operator=(MyClass&& other) {
// 移动赋值运算符的实现
delete this->p; // 释放原有的内存
this->p = other.p; // 浅拷贝
other.p = nullptr;
return *this;
}
private:
int* p;
};
析构函数
析构函数是对于一个对象而言最后会被执行的函数,用来释放对象所占用的资源。当对象在程序中被删除,或销毁时,会自动调用析构函数。
class MyClass {
public:
~MyClass() {
// 析构函数的实现
delete this->p;
}
private:
int* p;
};
需要注意的是,如果我们的类中有指针类型的成员变量,需要在析构函数中显式地释放内存,否则会造成内存泄漏。
示例
下面是一个使用特殊成员函数示例:
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "调用默认构造函数" << std::endl;
this->p = new int(0);
}
MyClass(const MyClass& other) {
std::cout << "调用拷贝构造函数" << std::endl;
this->p = new int(*other.p); // 假设p是指针类型的成员变量
}
MyClass(MyClass&& other) {
std::cout << "调用移动构造函数" << std::endl;
this->p = other.p;
other.p = nullptr;
}
MyClass& operator=(const MyClass& other) {
std::cout << "调用拷贝赋值运算符" << std::endl;
if (this == &other) {
return *this;
}
delete this->p;
this->p = new int(*other.p);
return *this;
}
MyClass& operator=(MyClass&& other) {
std::cout << "调用移动赋值运算符" << std::endl;
delete this->p;
this->p = other.p;
other.p = nullptr;
return *this;
}
~MyClass() {
std::cout << "调用析构函数" << std::endl;
delete this->p;
}
private:
int* p;
};
int main() {
MyClass obj1; // 调用默认构造函数
MyClass obj2(obj1); // 调用拷贝构造函数
MyClass obj3(std::move(obj1)); // 调用移动构造函数
MyClass obj4;
obj4 = obj2; // 调用拷贝赋值运算符
obj4 = std::move(obj2); // 调用移动赋值运算符
return 0;
}
输出结果为:
调用默认构造函数
调用拷贝构造函数
调用移动构造函数
调用默认构造函数
调用拷贝赋值运算符
调用移动赋值运算符
调用析构函数
调用析构函数
调用析构函数
调用析构函数
其中,obj1的值被移动到obj3中,obj2的值被拷贝到obj4中,各个对象的特殊成员函数被自动调用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一起聊聊C++中的特殊成员函数 - Python技术站