1

私はPImplをかなり広範囲に使用しており、自分が困惑していることに気付いたのは、Pimpl構造体のメンバーを正確に初期化する場所です。オプションは、Private構造体のコンストラクターを作成してそこで初期化するか、メインクラスのコンストラクターで初期化することです。

myclass.hpp:

class MyClass {
public:
    MyClass();
    ~MyClass();
private:
    struct Private; unique_ptr<Private> p;
};

myclass.cpp:

#include "myclass.hpp"
#include <string>

struct MyClass::Private {
    int some_var;
    std::string a_string;

    // Option A
    Private() :
        some_var {42},
        a_string {"foo"}
    {}
};

MyClass::MyClass() : p(new MyClass::Private) {
    // Option B
    p->some_var = 42;
    p->a_string = "foo";
}

Private現時点では、何らかの理由で新しいオブジェクトを作成したり、それらをコピーしたりする場合を除いて、2つの違いはあまりわかりません。その場合は、オプションAの方が適している可能性があります。また、初期化リスト内の変数を初期化することもできます。しかし、オプションBの方が読みやすく、おそらく保守しやすい傾向があることがわかりました。スケールをどちらかの方向に傾ける可能性のあるものがここにありますか?

4

2 に答える 2

5

必ず、RAII アプローチに従い、Private型のメンバーを初期化してください。ローカルに (さらに重要なことに、論理的な場所に) 保持しておけば、メンテナンスに感謝します。さらに重要なことに、オプション A を使用すると、const メンバーを持つことができます。

MyClassctorから値を渡す必要がある場合は、適切なコンストラクターを作成してPrivateください。

struct MyClass::Private {
    int const some_var; // const members work now
    std::string a_string;

    // Option C
    Private(int const some_var, std::string const& a_string) :
        some_var {some_var},
        a_string {a_string}
    {}
};

MyClass::MyClass() : p(new MyClass::Private(42,"foo")) {
}

そうしないと、Privateメンバーはデフォルトで構築され、後で上書きされるだけになります (これはints には関係ありませんが、より複雑な型はどうでしょうか?)。

于 2012-04-02T20:13:39.337 に答える
1

上記の @Charles Salvia が既に述べたように、変数は値が割り当てられる前にデフォルトで構築されるため、2 つのコンストラクターのいずれかでの割り当てにはオーバーヘッドが発生します。もちろん、このオーバーヘッドの量は、変数のタイプに大きく依存します。

これを受け入れることができる場合は、最も読みやすいバージョンを使用するのが最善だと思います。したがって、 のコンストラクターでの代入がMyClass最も読みやすいと思われる場合は、それを選択してください。

Privateただし、メンバー変数にデフォルトのコンストラクターがない場合、または参照または定数を使用する場合など、イニシャライザー リスト (c'tor用) を回避する方法がないことを考慮してください。

ケースバイケースでこれを決定したいかもしれませんが、「常に」初期化子リストを使用すると、新しく追加されたデータメンバーに対して一貫性が保たれ、将来的に保証されます。

于 2012-04-02T20:22:27.800 に答える