More Effective C++:Item 27

9930 ワード

More Effective C++を温习し、Item 27に対してスタック内でオブジェクトを生成することを要求または禁止し、この文に考えを整理する.
コンパイル期間制御
オブジェクトの定義に必要な条件を無効にすることで、コンパイル中にオブジェクトの定義をブロックします.次の表に、異なる場所で異なる形式のオブジェクト定義に必要な関数への最小アクセス権を示します.
class operator new
コンストラクタ
←ヒープ内オブジェクト ヒープ外オブジェクト→
コンストラクタ
class operator new
public
public
どくりつけいしき
public
private
private
public
直接メンバー形式
public
private
public
public
ポインタメンバー形式


private
protected
ベースクラス形式
protected
private
注意:
  • は、擬似構造関数を提供することによって、class operator newおよび構造関数へのポインタオブジェクトの依存から解放することができる.
  • 非スタックオブジェクトのポインタメンバー形式は存在しません.
  • ベースクラスオブジェクトのclass operator newは、派生クラスが関数を再ロードできるため必須ではありません.
  • メンバーオブジェクトのclass operator newは、クラス全体が呼び出される必要がないため、必要ではありません.

  • 結論:
  • 独立形式:class operator newをprivateと宣言することによってオブジェクト定義をスタック上で禁止することができ、コンストラクション関数をprivateと宣言し、擬似コンストラクション関数を提供すると、オブジェクト定義の再スタック上でオブジェクト定義を制限することができます.
  • ポインタメンバー形式:
  • 直接メンバー形式とベースクラス形式:定義条件はまったく同じで、制限できません.
  • //    。
    class Number
    {
    public:
        //        。
        static Number* MakeInstance() { return new Number; } 
        virtual ~Number() {}
    protected:
        //         protectedNumber() {} 
    };
    
    //==============================================================================
    //     。
    //==============================================================================
    
    void DefineIndependentObject()
    {
        //==========================================================================
        //      :  。
        //==========================================================================
    
        Number* heapObject = Number::MakeInstance();
        delete heapObject;
    
        //==========================================================================
        //      :  。
        //==========================================================================
    
        Number nonheapObject;
    }
    
    //==============================================================================
    //     。
    //==============================================================================
    
    void DefineMemberObject()
    {
        //==========================================================================
        //      :  。
        //==========================================================================
        {
            //             。
            class Asset
            {
            public:
                Asset() : value( Number::MakeInstance() ) {}
                ~Asset() { delete value; }
            private:
                Number* value;
            };
    
            Asset* heapObject = new Asset;
            delete heapObject;
        }
    
        //==========================================================================
        //      :  。
        //==========================================================================
        {
            //           。
            class Asset { private: Number value; };
    
            Asset nonheapObject;
        }
    }
    
    //==============================================================================
    //     
    //==============================================================================
    
    void DefineSubclassObject()
    {
        //          。
        class NegativeNumber : public Number {};
    
        //==========================================================================
        //      :  。
        //==========================================================================
    
        NegativeNumber* heapObject = new NegativeNumber;
        delete heapObject;
    
        //==========================================================================
        //      :  。
        //==========================================================================
    
        NegativeNumber nonheapObject;
    }

    スタック内のオブジェクトの抑制
    public class newを無効にするだけで、独立したオブジェクトがスタック内に定義されず、非スタック位置での定義に影響を与えません.
    しかし、public構造と構造関数を定義してこそ、非スタック位置に定義できるため、メンバーオブジェクトとベースクラスオブジェクトには良い方法はありません.しかし、スタックに定義できるようになります.同様に、構造関数または構造関数をprivateとして定義すると、それらの定義は完全に禁止されます.
    #include <new>
    
    class Number
    {
    private:
        static void* operator new( std::size_t ) throw() { return nullptr; }
    };
    
    //==============================================================================
    //     。
    //==============================================================================
    
    void DefineIndependentObject()
    {
        //==========================================================================
        //      :  。
        //==========================================================================
    
        Number* heapObject = new Number;
        delete heapObject;
    
        //==========================================================================
        //      :  。
        //==========================================================================
    
        Number nonheapObject;
    }

    じっこうきかんせいぎょ
    スタックオブジェクトと非スタックオブジェクトの異なる作成プロセスによって制御されます.異なる点は、スタックオブジェクトを作成するとclass operator newが呼び出される点だけです.しかし、まず、この点は独立したオブジェクトにのみ適用されます.ベースクラススタックオブジェクトとメンバースタックオブジェクトのclass operator newは必ずしも呼び出されません.
    #include <new>
    #include <iostream>
    
    class Number
    {
    public:
        static void* operator new( std::size_t ) throw() 
        {
            std::cout << "class operator new for Number" << std::endl;
        }
    };
    
    class NegativeNumber : public Number
    {
    public:
        static void* operator new( std::size_t ) throw() 
        {
            std::cout << "class operator new for NegativeNumber" << std::endl;
        }
    };
    
    class Asset { Number value; };
    
    int main()
    {
        //       class operator new   。
        Number* independentObject = new Number;
        delete independentObject;
    
        //  ,            。
        NegativeNumber* baseObject = new NegativeNumber;
        delete baseObject;
    
        //  ,            。
        Asset* memberObject = new Asset;
        delete memberObject;
    
        return 0;
    }

    そして、独立したオブジェクトでもあまり使いにくいので、具体的にはMore Effective C++Item 27を参照してください.
    まとめ
    制御対象のメモリ位置が困難で、完璧に実現できるのは:1.スタック内に独立したオブジェクトとメンバーオブジェクトが必要です.2.独立したオブジェクトがオブジェクトにあることを禁止します.