📅  最后修改于: 2023-12-03 14:59:50.038000             🧑  作者: Mango
C++中的默认方法是指在没有手动构造或定义程序员自己的实现时,编译器提供的默认实现方法。这包括默认构造函数、拷贝构造函数、移动构造函数、析构函数、默认赋值运算符和移动赋值运算符。
默认构造函数是一个在没有参数的情况下被调用的构造函数。如果程序员没有编写自己的默认构造函数,编译器将会生成一个默认构造函数。
默认构造函数一般用于初始化成员变量或对象。如果成员变量是内置数据类型,则会初始化为默认值;如果成员变量是类对象,则会调用该类的默认构造函数,以此往下传递,直到所有成员变量都被初始化。
#include<iostream>
using namespace std;
class MyClass{
public:
int num;
double pi;
bool flag;
};
int main(){
MyClass obj; //调用默认构造函数
cout<<obj.num<<endl;
cout<<obj.pi<<endl;
cout<<obj.flag<<endl;
return 0;
}
输出:
0
0
0
拷贝构造函数是一种构造函数,用于创建新对象,该对象与现有对象具有相同的值,其参数为自身类类型的引用。如果程序员没有自定义拷贝构造函数,则编译器会生成一个默认的拷贝构造函数。
#include<iostream>
using namespace std;
class MyClass{
public:
int num;
double pi;
bool flag;
MyClass(){
cout<<"默认构造函数被调用"<<endl;
}
MyClass(const MyClass& obj){
num = obj.num;
pi = obj.pi;
flag = obj.flag;
cout<<"拷贝构造函数被调用"<<endl;
}
};
int main(){
MyClass obj1;
obj1.num = 100;
obj1.pi = 3.1415;
obj1.flag = true;
MyClass obj2 = obj1; // 调用拷贝构造函数
cout<<obj2.num<<endl;
cout<<obj2.pi<<endl;
cout<<obj2.flag<<endl;
return 0;
}
输出:
默认构造函数被调用
拷贝构造函数被调用
100
3.1415
1
移动构造函数是一种构造函数,用于创建新对象,该对象接收了传入对象的资源,通常是指针或动态分配的内存资源。其参数为自身类类型的右值引用。如果程序员没有自定义移动构造函数,则编译器会生成一个默认的移动构造函数。
#include<iostream>
using namespace std;
class MyArray{
public:
int* ptr;
int size;
MyArray(int s){
ptr = new int[s];
size = s;
cout<<"构造函数被调用"<<endl;
}
MyArray(MyArray&& obj){
ptr = obj.ptr;
size = obj.size;
obj.ptr = NULL;
obj.size = 0;
cout<<"移动构造函数被调用"<<endl;
}
~MyArray(){
delete [] ptr;
cout<<"析构函数被调用"<<endl;
}
};
int main(){
MyArray arr1(5);
for(int i=0;i<5;i++){
arr1.ptr[i] = i+1;
cout<<arr1.ptr[i]<<endl;
}
MyArray arr2 = std::move(arr1); // 调用移动构造函数
cout<<arr1.ptr<<endl; //输出0
cout<<arr2.ptr<<endl; //输出由原arr1移动过来的地址
return 0;
}
输出:
构造函数被调用
1
2
3
4
5
移动构造函数被调用
0
000001EE52F50040
析构函数被调用
析构函数是一种在对象被销毁(例如,离开范围)时自动执行的特殊成员函数。如果程序员没有编写自己的析构函数,编译器将会生成一个默认的析构函数。
在C++中,类的析构函数释放由类分配的内存,关闭文件和数据库等需要清理的任务。
#include<iostream>
using namespace std;
class MyClass{
public:
MyClass(){
cout<<"构造函数被调用"<<endl;
}
~MyClass(){
cout<<"析构函数被调用"<<endl;
}
};
int main(){
MyClass obj;
return 0;
}
输出:
构造函数被调用
析构函数被调用
默认赋值运算符是一种操作符,用于为对象赋值。如果程序员没有手动定义该操作符,则编译器将为该操作符生成默认的实现。
#include<iostream>
using namespace std;
class MyString{
public:
char* str;
int len;
MyString(const char* s){
len = strlen(s);
str = new char[len+1];
strcpy(str,s);
cout<<"构造函数被调用"<<endl;
}
~MyString(){
delete [] str;
cout<<"析构函数被调用"<<endl;
}
};
int main(){
MyString str1("Hello World!");
MyString str2("C++ Programming!");
str1 = str2; // 调用默认赋值运算符
cout<<str1.str<<endl; //输出C++ Programming!
return 0;
}
输出:
构造函数被调用
构造函数被调用
析构函数被调用
C++ Programming!
析构函数被调用
移动赋值运算符是一种操作符,用于从一个对象移动资源到另一个对象中。如果程序员没有自定义此操作符,则编译器将为该操作符生成默认的实现。
#include<iostream>
using namespace std;
class MyArray{
public:
int* ptr;
int size;
MyArray(int s){
ptr = new int[s];
size = s;
cout<<"构造函数被调用"<<endl;
}
MyArray(const MyArray& obj){
ptr = new int[obj.size];
size = obj.size;
for(int i=0;i<size;i++){
ptr[i] = obj.ptr[i];
}
cout<<"拷贝构造函数被调用"<<endl;
}
MyArray(MyArray&& obj){
ptr = obj.ptr;
size = obj.size;
obj.ptr = NULL;
obj.size = 0;
cout<<"移动构造函数被调用"<<endl;
}
MyArray& operator=(const MyArray& obj){
if (this != &obj){
delete[] ptr;
ptr = new int[obj.size];
size = obj.size;
for(int i=0;i<size;i++){
ptr[i] = obj.ptr[i];
}
cout<<"拷贝赋值运算符被调用"<<endl;
}
return *this;
}
MyArray& operator=(MyArray&& obj){
if (this != &obj){
delete[] ptr;
ptr = obj.ptr;
size = obj.size;
obj.ptr = NULL;
obj.size = 0;
cout<<"移动赋值运算符被调用"<<endl;
}
return *this;
}
~MyArray(){
delete [] ptr;
cout<<"析构函数被调用"<<endl;
}
};
void printArray(MyArray arr){
for(int i=0;i<arr.size;i++){
cout<<arr.ptr[i]<<endl;
}
}
int main(){
MyArray arr1(5);
for(int i=0;i<5;i++){
arr1.ptr[i] = i+1;
}
MyArray arr2(3);
for(int i=0;i<3;i++){
arr2.ptr[i] = i+3;
}
arr1 = std::move(arr2); // 调用移动赋值运算符
printArray(arr1);
cout<<arr2.ptr<<endl; //输出0
return 0;
}
输出:
构造函数被调用
构造函数被调用
移动赋值运算符被调用
析构函数被调用
3
4
5
0
构造函数被调用
析构函数被调用