クラスのオブジェクトインスタンスを制限する方法は、スタックにのみ割り当てるか、スタックにのみ割り当てるかです.

6995 ワード

原文住所:https://blog.csdn.net/szchtx/article/details/12000867
C++では、クラスのオブジェクト確立は2つに分けられ、1つはA aのような静的確立である.もう1つは、A*ptr=new Aなどの動的確立である.この2つの方法には違いがある.
スタティックはクラスオブジェクトを確立し、コンパイラによってオブジェクトにスタック空間にメモリを割り当て、スタックトップポインタを直接移動して適切な空間を移動し、このメモリ空間でコンストラクション関数を呼び出してスタックオブジェクトを形成します.この方法を使用して、クラスの構造関数を直接呼び出します.
クラスオブジェクトを動的に作成するには、new演算子を使用してオブジェクトをスタック空間に作成します.このプロセスは2つのステップに分けられ、最初のステップはoperator new()関数を実行し、スタック空間で適切なメモリを検索して割り当てます.2つ目のステップは、コンストラクション関数コンストラクションオブジェクトを呼び出し、このメモリ領域を初期化することです.この方法では,クラスの構造関数を間接的に呼び出す.
では、クラスオブジェクトがスタックまたはスタック上にしか作成できないことをどのように制限しますか?以下、それぞれ検討する.
1.スタック上にしか構築できない
クラスオブジェクトはスタックにのみ作成できます.つまり、クラスオブジェクトを静的に作成できません.つまり、クラスの構造関数を直接呼び出すことはできません.
方法1: を思い浮かべやすい.コンストラクション関数がプライベートになった後、クラス外部でコンストラクション関数を呼び出してクラスオブジェクトを構築することはできません.new演算子を使用してオブジェクトを構築するしかありません.しかし、前述したように、new演算子の実行プロセスは2つのステップに分けられ、C++はnew演算子のリロードを提供し、実際にはoperator new()関数のリロードのみを許可し、operator()関数はメモリの割り当てに使用され、構造機能を提供できない.そのため、この方法はできません.
方法2:オブジェクトがスタックの上に構築されると、コンパイラによってメモリ空間が割り当てられ、コンストラクション関数を呼び出してスタックオブジェクトを構築します.オブジェクトが使用されると、コンパイラは構造関数を呼び出してスタックオブジェクトが占める空間を解放します.コンパイラは、オブジェクトのライフサイクル全体を管理します.コンパイラがクラスの構造関数を呼び出せない場合、どうなりますか?たとえば、 では、コンパイラは構造関数を呼び出してメモリを解放できません. , , , , , 。 , 。
したがって、構造関数をプライベートに設定すると、クラスオブジェクトはスタックに構築できません.コードは次のとおりです.
class A
{
public:
    A(){}
    void destory(){delete this;}
private:
    ~A(){}
};

A aを使ってみます.をクリックしてオブジェクトを作成し、エラーをコンパイルし、構造関数にアクセスできないことを示します.これによりnewオペレータを使用してオブジェクトを作成するしかなく、コンストラクション関数は共通であり、直接呼び出すことができます.クラスには、メモリ領域の解放を行うdestory関数が必要です.クラスオブジェクトの使用が完了したら、destory関数を呼び出す必要があります.
上記の方法の1つの欠点は,継承問題を解決できないことである.Aが他のクラスのベースクラスである場合、構造関数は通常virtualに設定され、サブクラスで書き換えてマルチステートを実現します.したがって、構造関数をprivateに設定することはできません.C++は3番目のアクセス制御、protectedを提供しています. protected , protected , 。
もう1つの問題は、クラスの使用が不便で、newを使用してオブジェクトを構築しますが、deleteではなくdestory関数を使用してオブジェクトを解放します.(deleteを使用するとエラーが表示されます.deleteオブジェクトのポインタは、オブジェクトの構造関数を呼び出しますが、構造関数クラス以外はアクセスできません)という使用方法は奇妙です.統一するために、構造関数をprotectedに設定し、publicのstatic関数を提供して構造を完了することができ、newではなく、1つの関数を使用して構造し、1つの関数を使用して構造を解析することができます.コードは次のとおりです.単一のモードと似ています.
class A
{
protected:
    A(){}
    ~A(){}
public:
    static A* create()
    {
        return new A();
    }
    void destory()
    {
        delete this;
    }
};

これにより、create()関数を呼び出してスタック上にクラスAオブジェクトを作成し、destory()関数を呼び出してメモリを解放します.
2.スタックにのみ作成可能
new演算子を使用している場合にのみ、オブジェクトはスタックに構築されます.したがって、new演算子を無効にすると、クラスオブジェクトはスタックにのみ構築されます.operator new()をプライベートにすればいいです.コードは次のとおりです.
class A
{
private:
    void* operator new(size_t t){}     //                    
    void operator delete(void* ptr){} //    new     delete
public:
    A(){}
    ~A(){}
};