C++ のコンストラクターとデストラクター

1. はじめに

C++ では、コンストラクターは、クラスのオブジェクトを初期化するために使用される特別なメンバー関数です。构造函数的名称与类的名称相同,没有返回值类型,也不需要使用void关键字。构造函数可以有参数和重载, そのため、異なるパラメーター リストに基づいて異なるオブジェクトを作成できます。
コンストラクターはオブジェクトの作成時に自動的に呼び出され、メンバー変数への初期値の代入やメモリの割り当てなど、オブジェクトの初期化を完了するために使用されます。コンストラクターでメンバー初期化リストを使用してメンバー変数に初期値を割り当てることができます。また、コンストラクター本体で代入操作を実行することもできます。

2 番目に、コンストラクター

C++ はコンストラクターを使用して、オブジェクトが占有するメモリの割り当てを実現します。コンストラクタは、オブジェクトが初期化されるときに強制されます。コンストラクタを自分で実装しない場合、コンパイラはデフォルトのコンストラクタを提供します。コンストラクタは特別なメンバー関数であり、主にオブジェクトに領域を割り当てて初期化するために使用されます
コンストラクターの名前はクラス名と同じである必要があり、ユーザーが任意に名前を付けることはできません。任意の型のパラメータを持つことができますが、戻り値を持つことはできません。ユーザーが呼び出す必要はありませんが、オブジェクトの作成時にコンパイラーによって自動的に実行されます。new を使用する場合、まず malloc を呼び出してヒープ領域を適用し、次にコンストラクターを呼び出して要求された領域に値を割り当てます。

2.1 コンストラクターの分類

コンストラクターには次の特別な型があります。

  • デフォルトのコンストラクター:パラメーターのないコンストラクター。コンストラクターが定義されていない場合、コンパイラーはデフォルトのコンストラクターを自動的に生成します。
  • コピー コンストラクター:既存のオブジェクトを新しく作成されたオブジェクトにコピーするために使用され、パラメーターは同じ型の参照または定数参照です。
  • 移動コンストラクター:右辺値によって参照されるオブジェクトのリソースを新しく作成されたオブジェクトに転送するために使用されます。パラメーターは同じ型の右辺値参照です。
  • デストラクタ:オブジェクトが占有しているリソースを解放するために使用されます。パラメータや戻り値の型はありません。名前はクラス名に "~" を加えたものです。

コンストラクターの定義と使用例:

class MyClass{
public:
    //默认构造函数
    MyClass(){
        num = 0;
        str = "default";
    }
    //有参数的构造函数
    MyClass(int n, string s){
        num = n;
        str = s;
    }
    //拷贝构造函数
    MyClass(const MyClass& other){
        num = other.num;
        str = other.str;
    }
    //移动构造函数
    MyClass(MyClass&& other){
        num = other.num;
        str = std::move(other.str);
        //转移右值引用的资源
        other.num = 0;
        other.str.clear();
    }
    //析构函数
    ~MyClass(){
        //释放资源
    }
private:
    int num;
    string str;
};
int main() {
    MyClass obj1; // 调用默认构造函数
    MyClass obj2(10, "Hello"); // 调用有参数的构造函数
    MyClass obj3 = obj1; // 调用拷贝构造函数
    MyClass obj4 = std::move(obj2); // 调用移动构造函数
    return 0;
}

2.2 コンストラクターの構文

  • コンストラクターの名前はクラス名と同じである必要があります。そうでない場合、コンパイラーはそれを一般のメンバー関数として扱います。
  • コンストラクターには戻り値がなく、コンストラクターを定義するときにその型を指定することはできません。
  • 通常のメンバー関数と同様、コンストラクターの関数本体はクラス内またはクラス外に記述できます。
  • コンストラクターは通常、パブリック メンバーとして宣言されますが、他のメンバー関数のように明示的に呼び出す必要はなく、また呼び出すこともできません。オブジェクトが定義されるときに自動的に呼び出され、実行されるのは 1 回だけです。
  • コンストラクターはパラメータを取ることができません。
#include<iostream>
using namespace std;
#include<string>
#include<vector>
/*
private 私有的:只有当前类内才有权限访问这个成员(类内)
protected 受保护的:类内和子类有权限访问这个成员(类内子类)
public 公共的:所有位置都有权限访问这个成员(对象,子类,类内)
*/

class people {
private:      //私有的     不可以被对象访问
	int age;
protected:    //受保护的    内类和子类能访问
	bool Gender;
public:       //共有的类内 子类 对象都可以访问
	string name;
	//构造函数的名字和类名相同,有参数(能重载),没有返回值
	people() {
		cout << "无参构造" << endl;
	}
	people(int A) {
		cout << "调用了参数为int A的构造函数" << endl;
	}
	/*people(int A, bool G, string N) {
		age = A;
		Gender = 0;
		name = N;
		cout << "调用了参数为int A,bool G,string N的构造函数" << endl;
	}*/

	people(int age, bool Genger, string name) {
		this->age = age;//this 是个指针,指向了当前对象,this的主要作用是区分成员变量和参数
	}
};
int main() {
	people p1(12);
	people p2(12, 1, "asd");
	people p3;//调用无参构造 如果是people p() 编译器会认为是函数声明不会创建对象
	cout << -------------------------- << endl;
	//在堆区创建对象C++中使用关键字 new,释放堆区内存使用关键字delete
	people *Q = new people();//调用了无参构造函数在堆区创建了对象
	people* Q1 = new people(1);//调用了参数为int A 的构造函数创建了堆区对象
	//释放堆区内存
	delete Q;
	delete Q1;
	//在堆区创建int类型的数组
	int* int_ps = new int[3];//在堆区申请了12个字符的内存
	cout << int_ps[0] << int_ps[1] << int_ps[2] << endl;
	delete[]int_ps;//释放堆区数组要加[]
	//在堆区创建people类型的数组
	people* peo_ps = new people[3];//在堆区创建了3个people类型的对象
	delete[]peo_ps;
	return 0;
}

オブジェクトの作成中に、コンストラクターを使用して、通常は次の形式でデータ メンバーに値を割り当てます。

类名 对象名[(实参表)]
Score op1(99, 100);
op1.showScore();
类名 *指针变量名 = new 类名[(实参表)]
Score *p;
p = new Score(99, 100);
p->showScore();
-----------------------
Score *p = new Score(99, 100);
p->showScore();

3. デストラクター

C++ では、デストラクターはクラス内の特別なメンバー関数であり、オブジェクトが破棄されたときにリソースを解放してクリーンアップする(オブジェクトの内部ポインターが指すヒープ メモリをクリアする) ために使用されます。デストラクター名はクラス名と同じですが、名前の前にチルダ (~) が付きます。
** 析构函数没有返回值,也没有参数,页不能重载。**したがって、
その申告書は次のとおりです。

class MyClass{
public:
    //构造函数
    MyClass();
    //析构函数
    ~MyClass();
};

オブジェクトが破棄されると、そのデストラクターが自動的に呼び出されます。オブジェクトの破棄は、プログラマが明示的に delete 演算子、delete[] 演算子を呼び出すか、オブジェクトのライフサイクルの終了時に自動的にデストラクターを呼び出すことによって実行できます (スタック オブジェクトは自動的に解放され、ヒープ オブジェクトは手動で解放される必要があります)。 delete または delete[] 演算子呼び出しを呼び出します)。デストラクターの主な機能はリソースを解放し、操作をクリーンアップすることであるため、通常は、動的に割り当てられたメモリの解放、ファイル ハンドルのクローズ、ネットワーク接続の解放など、
いくつかのオブジェクトのクリーンアップ操作をデストラクター内で完了しますデストラクターで動的に割り当てられたメモリを解放する方法を示す簡単な例を次に示します。

#include<iostream>
#include<string>    //C++中,string是类,里面包含了方法和属性
using namespace std;
class MyClass{
    int a;
    int b;
    int* p = NULL;
    int* p1 = NULL;
public:
    MyClass(){}
    MyClass(int a){
        p = new int(a);
        p1 = new int [a];
    }
    ~MyClass(){
        if(p) delete p;
        if(p1) delete[] p1;
        cout << "析构函数" << endl;
    }
};
int main(){
    MyClass p(5);
    MyClass* p1 = new MyClass(6);
    delete p1;
    return 0;
}

説明:次の場合、オブジェクトのライフサイクルが終了すると、デストラクターが自動的に呼び出されます。

  • オブジェクトがスタック領域に作成されると、オブジェクトがスコープ外に出ると、そのデストラクターが自動的に呼び出されます。
void someFunction(){
    MyClass obj;    //创建对象
    //对象声明周期结束,离开作用域
}   //obj的析构函数自动被调用
  • ヒープ領域にオブジェクトが作成されたとき、delete 演算子を使用してオブジェクトが解放されるときに、オブジェクトのデストラクターが自動的に呼び出されます。
void someFuntion(){
    MyClass* pObj = new MyClass(0;    //在堆区创建对象
    //在这里使用对象
    delete pObj;    //释放对象
    //pObj的析构函数自动被调用
}
  • オブジェクトが別のオブジェクトのメンバーである場合、そのオブジェクトを含むオブジェクトが破棄されると、オブジェクトのデストラクターが自動的に呼び出されます。
class MyContainer{
public;
    MyContainer(){
        pObj = new MyClass();    //创建一个MyClass对象
    }
    ~Mycontainer(){
        delete pObj;    //释放MyClass对象
    }
private:
    MyClass* pObj;
};

上記の例では、MyContainer オブジェクトが破棄されると、それに含まれる M オブジェクトと Class オブジェクトのデストラクターも自動的に呼び出されます。
コード例:

#include<iostream>
#include<string>//C++中 string是类,里面包含了方法 和 属性
#include<vector>
using namespace std;

class A {
public:
    //析构函数
	int* p;    //p属于对象,对象在堆区,p就在堆区
	A(int size) {
		p = new int[size];
	}//堆区没有释放,会造成内存泄漏
	//栈区对象自动释放,堆区对象手动释放,都会自动调用析构函数

    //析构函数
	~A() {
		if (p) {
			delete p;
			p = nullptr;    //将p赋值成空指针
		}
		cout << "析构函数" << endl;
	}
};

int main(){
    //A a(3);           //错误
	A* a = new A(3);    //p指针又指向一个堆区
	//不执行析构函数
	//析构函数是在释放对象时自动调用
	delete a;//释放a指向的堆区对象,从而调用析构函数
	return 0;
}//析构函数是为了释放对象里面的指针 指向堆区内存
----------------------------------------------------------------------------------
//输出“析构函数”

4 番目、デフォルトのコンストラクターとデストラクター

デフォルトのコンストラクタとデストラクタは、C++ のすべてのクラスのメンバ関数であり、明示的に定義されていない場合は、コンパイラによって提供されるデフォルトの実装に従って実行されます。

4.1 機能

  • デフォルトのコンストラクター (パラメーターのないコンストラクター):クラス オブジェクトの作成時に、オブジェクトのメンバー変数を初期化するために使用されます。コンストラクターが明示的に定義されていない場合、コンパイラーはパラメーターを受け取らず、オブジェクトのメンバー変数をデフォルト値に初期化するデフォルトのコンストラクターを提供します (たとえば、数値型は 0 に初期化され、ポインター型は nullptr、Boolean に初期化されます) type は false に初期化されるなど)。
  • デフォルトのデストラクター (パラメーターのないデストラクター):オブジェクトのライフサイクルの終了時に、オブジェクトによって占有されているリソースを解放するために使用されます。如果对象有成员变量是指针类型,那么默认析构函数只会释放这些指针所指向内存,而不会释放指针本身的内存。デストラクターが明示的に定義されていない場合、コンパイラーはパラメーターを受け取らず、オブジェクトが占有しているメモリー空間を解放するデフォルトのデストラクターを提供します。

知らせ:
如果类中有成员变量是指针类型,并且这些指针指向的内存是通过 new 运算符分配的,那么就需要自己编写析构函数来释放这些内存。否则类中可能会出现内存泄露问题。

たとえば、次は整数型のメンバー変数とポインター型のメンバー変数を含む単純なクラスの例です。

class MyClass{
public:
    MyClass();    //默认构造函数
    ~MyClass();   //默认析构函数
private:
    int m_num;
    int* m_ptr;
};

上記の例では、Myclass のコンストラクターとデストラクターが明示的に定義されていない場合、コンパイラーはデフォルトの実装を提供します。デフォルトのコンストラクターとデストラクターは、次の方法で明示的に定義できます。

MyClass::MyClass(){
    //默认构造函数的实现
}
MyClass::~MyClass(){
    //默认析构函数的实现
}

例証します:

  • コンストラクターを定義していないクラスの場合、そのパブリック データ メンバーは初期化パラメーター リストを使用して初期化できます。
class MyClass{
public:
    char name[10];
    int age;
};

MyClass my= {"chen", 23};
cout << my.name << my.age << endl;

コンストラクターはオーバーロードできます。つまり、オブジェクトを作成するためのさまざまなパラメーター オプションを提供するために、異なる形式の複数のコンストラクターをクラス内で定義できます。オブジェクトを作成するとき、システムは渡されたパラメーターのタイプと数に基づいて呼び出すコンストラクターを選択します。

例: 2 つのコンストラクターを定義するクラスの例を次に示します。

class MyClass{
public:
    MyClass(){
        //无参构造函数
    }
    MyClass(int value){
        //带有一个int类型参数的构造函数
        m_value = value;
    }
private:
    int m_value;
};

おすすめ

転載: blog.csdn.net/m0_62573214/article/details/131878049