1

私はクラスを持っています:

class Nothing
{

    /// Constructor, Destructor, Copy and Assignment
    public:
    Nothing();
    ~Nothing();
    Nothing(const Nothing& clone);

    /// Operators
    const Nothing& operator=(const Nothing& other);

    /// Static Members
    private:
    static unsigned long long id_counter;
    static unsigned long long instance_counter;
};


Nothing::Nothing()
{
    m_name.clear();
    id_counter ++;
    m_id = id_counter;

    instance_counter ++;
}

Nothing::~Nothing()
{
    m_name.clear();
    instance_counter --;
}

Nothing::Nothing(const Nothing& other)
{

}

unsigned long long Nothing::id_counter = 0;
unsigned long long Nothing::instance_counter = 0;

クラスのインスタンスをカウントするために unsigned long long を使用していることに注意してください。代わりに std::size_t を使用する必要がありますか?

余談ですが、クラスのインスタンスがあり、次のようなことをするとします。

Nothing instance;
instance(Nothing()); // Calling copy constructor

コピーコンストラクタが呼び出される前にデストラクタが呼び出されますか? 質問する理由は、コピーコンストラクターの中id_counter ++;に必要ですか?instance_counter ++;

4

4 に答える 4

2

en.cppreferenceでわかるように、 std::size_t 定義は実装固有です。ほとんどの実装では、 として定義されていることがわかりますunsigned int

したがって、あなたの質問に答えるために、必要にunsigned long long応じて代わりにそれを使用することができ、 std::size_t が保証されているという意味で、コードは(実際に64ビットの長さである必要がない限り)移植性を維持しますすべての C++ コンパイラで定義されます。要件が必須である場合unsigned long long(インスタンス カウントに使用しているので疑わしい)、 に固執するのが最善unsigned long longです。

instance(Nothing); // Calling copy constructor: Should this be `instance(Nothing())`?

これは悪い構文です。copy ctor新しく形成されたインスタンスでを呼び出そうとしている場合は、 を呼び出す必要がありますNothing copyInstance (Nothing());。もちろん、「クリーンな」インスタンスをコピーしているので、これを行うのは非常にばかげていますNothing copyInstance;。同じ効果を呼び出すこともできます。

id_counter ++ が必要ですか? および instance_counter ++; 私のコピーコンストラクターの中に?

新しいインスタンスを作成しているので、instance_counter を確実にインクリメントする必要があります。id_counter が何をカウントするか (参照カウント??) を指定しなかったので、言うのは難しいです。

コピーコンストラクタが呼び出される前にデストラクタが呼び出されますか?

コードのどこにも が呼び出される場所はありませんが、スタックにdtor割り当てているため、そのデストラクタはそのスコープの最後に到達すると呼び出されます (次の出現)。instanceinstance}

于 2013-02-16T15:16:07.903 に答える
2

std::size_tは式の型であり、sizeof通常はSTL コンテナーによって返される型です。(技術的には、STL コンテナーはそれぞれ typedef aですが、ほとんどの場合は と同等です。)size()capacity()size_typestd::size_t

特殊なメモリ モデル (たとえば、"near" ポインターと "far" ポインターを区別するモデル) を備えたマシンを除いて、astd::size_tは常に、一度にメモリに収まるすべてのオブジェクトをカウントするのに十分な大きさになります。これは直接の保証ではなく、定義の書き方の副作用です。

したがって、std::size_tインスタンス数などの自然な型です。

std::size_tは符号なしタイプであることに注意してください。多くの人は、実際のビット パターンを表す場合を除き、符号なしの型は避けるべきだと考えています (たとえば、Google スタイル ガイドを参照してください)。unsigned 型を使用すると、一部の算術演算が驚くべき動作をする場合があります。インスタンス数が負になるバグがあった場合、負の値が非常に大きな正の値にラップアラウンドするため、検出が難しい場合があります。

個人的には、その議論には説得力がないと思います。符号付き算術演算は、オーバーフローとアンダーフローを処理するときにも驚くべき方法で動作します。また、STL 型を使用しようとしている場合、符号付きの値に割り当てsize()たり、符号付きの値を比較したりするにsize()は、明示的なキャストを行うか、コンパイラの警告を無効にする必要があります。コンパイラの警告を無効にするのは好きではありません。特に、署名されていない型を避けることを提案するときに人々が恐れる多くのバグを見つけるのに役立つからです。

私は使用しstd::size_tます。には何も問題はありunsigned long longませんが、ホスト プラットフォームに合わせてスケーリングできない可能性があります。

オプションを開いたままにしておく場合は、typedef を Nothing クラスに追加できます。これにより、後で簡単に変更できます。

/// Static Members
private:
typedef unsigned long long CounterType;  // consider std::size_t
static CounterType id_counter;
static CounterType instance_counter;

size_typeSTL コンテナーのスタイルに合わせたい場合は、typedef を呼び出すこともできます。

于 2013-02-16T16:48:39.160 に答える
1

技術的には、少なくとも近い将来、どちらも問題ないはずです。

linkおよびlinkで説明されているように、 は operatorsize_tの戻り値の型でありsizeof()、現在のプラットフォームで可能な最大のオブジェクトのサイズを保持することが保証されています。それも通常unsignedです。

ええ、unsigned long long近い将来、使用しても問題が発生する可能性はほとんどありません。ただし、最大の互換性で、たとえば 128 ビット環境に移行すると、さらにsize_t有利になる場合があります。


しかし、コードが少なくともunsigned long long0~2^64-1 を持つという事実に依存している場合、に切り替えるのはおそらく良い考えではありません。size_t


はい、コピーコンストラクターのカウンターを更新して、まっすぐにする必要があります。


PSなぜあなたがしたいのかわかりません:

Nothing instance; 
instance(Nothing);

static Nothing Nothing::instance()メンバー関数が新しいインスタンスを取得したいのかもしれません。//既存のインスタンスの代わりにの copy-ctor を呼び出す理由がわかりません。

そして、いつでもコンストラクターとデストラクタから呼び出して、実行順序を調べるprintf()ことができます。flush()

于 2013-02-16T15:41:33.373 に答える
1

クラスのインスタンスをカウントするために unsigned long long を使用しています。代わりに std::size_t を使用する必要がありますか?

使う理由も使わstd::size_tない理由もありませんstd::size_t。これは配列インデックスのようなものには便利なタイプですが ( unsigned int と size_tを参照)、特定のプログラムで作成できるオブジェクトの最大数とはまったく相関しません。そのため、どれだけ多くのオブジェクトを持っていると思うかに基づいて、好きなものを選択してください。

コピーコンストラクタが呼び出される前にデストラクタが呼び出されますか?

コピー コンストラクターをまったく呼び出していません。実際、コンストラクターを「呼び出す」ことはできません。コピー コンストラクターは、新しいオブジェクトを作成して既存のオブジェクトから初期化するときに自動的に呼び出されますが、コードのどこにもそれを行いません。

コピーコンストラクターの中id_counter ++;に必要ですか?instance_counter ++;

はい。

于 2013-02-16T15:22:34.253 に答える