📜  C++中带有示例的默认方法(1)

📅  最后修改于: 2023-12-03 14:59:50.038000             🧑  作者: Mango

C++中带有示例的默认方法

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
构造函数被调用
析构函数被调用