2016-08-03 7 views
0

私の質問を説明するために、次のコードを書いています。 LargeClassがクラスであり、次のコードが示すように多くの内部変数を含んでいるとします。 Abcクラスオブジェクトが構築されるときに初期化することが非常に高価である大きなクラスの要素をC++に組み込む方法

class Abc 
{ 
public: 
     std::vector<LargeClass> obj; 

}; 

std::vector<LargeClass>ように、一つの可能​​な解決策はである:

class LargClass 
{ 
    public: 
     std::vector<int> abc={1,2,3, ...., 10000}; 

} 

を、以下のコードが示すようLargeClassが別のクラスAbcの要素となると仮定しますAb30の後に構成要素std::vector<LargeClass>が次のコードとして構成されます。

Abc abcObj; 

abcObj.obj.resize(3); 
.... 
... 

の代わりにコストのかかる方法でstd::vector<LargeClass>を初期化します。もちろん

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> objTemp) 
     { 
      obj = objTemp; 
     } 
} 

他のソリューションがあります。一つの解決策は、このソリューションを使用すると、ポインタ

class Abc 
    { 
public: 
    Abc(std::vector<LargeClass> &obj) 
    { 
     pObj = &obj; 
    } 
std::vector<LargeClass> *pObj; 
} 

を使用することです、しかし、私たちは、与えられたstd::vector<LargeClass> &objは常にクラスAbcの寿命の間に存在することを確認する必要があります。この問題を解決するために、別の解決策はshared_ptrを使用することです:

class Abc 
     { 
    public: 
     Abc(boost::shared_ptr<std::vector<LargeClass>> obj) 
     { 
      pObj = obj; 
     } 
    boost::shared_ptr<std::vector<LargeClass> > pObj; 
    } 

だから私の質問は:優れているソリューション?私にとっては、最初の方が好きですが、オブジェクト指向プログラミングのルールに合っていません。助言がありますか?

+1

呼び出し元がstd :: move(http://en.cppreference.com/w/cpp/utility/move)を使用している場合、事前に初期化されたベクトルをコンストラクタに渡す場合にコストがかかることはありませんそれをコンストラクタ – nate

+0

に渡すと、 'LargeClass'のこれらのインスタンスは' ABC'とは独立して存在する必要がありますか、 'ABC'は完全所有権を取ることができますか? – user4581301

+0

あなたの例では、ベクトルは所有者であり、移動コンストラクタはあるベクトルから次のベクトルに所有権を渡します – nate

答えて

1

は、移動コンストラクタを使用します。

LargeClassがコピー可能な場合は、正しい使用を強制する2番目の方法をお勧めします。

LargeClassのコピーコンストラクタを削除することをお勧めします。コピーを避けたい場合(安価なムーブコンストラクタを実装する場合)

1

代わりの

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> objTemp) 
     { 
      obj = objTemp; 
     } 
} 

これはobjTempにいくつかのソースvectorのコピー建設の可能性、objのデフォルトの構造、およびobjTemp 2おそらく

objへのコピーのコピーを持っており、デフォルトの構造体。ヤッキー。

代わりMember Initializer List

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> & objTemp):obj(objTemp) 
     { 
     } 
} 

を活用するこれはobjTempを参照して、コピー構築objによる初期化の一部を排除します。 objTempを参照として宣言すると、コピー構成はobjTempになりません。

もこのトリックにパフォーマンス上の利点があるかもしれません:コンパイラはそうすることが適当と考える、その後、objに移動この場合objTemp

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> objTemp):obj(std::move(objTemp)) 
     { 
     } 
} 

は、コピー構築です。コンパイラはこれをシーンの背後でさらに微調整して大幅に節約できます。

objTempが完全に消耗品である場合は、

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> & objTemp):obj(std::move(objTemp)) 
     { 
     } 
} 

、あなたのコピーを保存し、objobjTempの内容を移動することができます。 objTempは完全に空になりました。もしあなたがABCの外にそれを必要としたなら、まあ...あなたのことを吸う。

ABCと別のものがすべてobjTempの所有権を持ち、互換性のない範囲を持っていない限り、私は共有ポインタを使用しません。 LargeClass可動のみ(コピー可能ではない)である場合、両方のソリューションは、主に等価である

class Abc 
{ 
public: 
    Abc(std::vector<LargeClass> objTemp) : obj(std::move(objTemp)) {} 

private: 
    std::vector<LargeClass> obj; 
}; 

又は

class Abc 
{ 
public: 
    Abc(std::vector<LargeClass>&& objTemp) : obj(std::move(objTemp)) {} 

private: 
    std::vector<LargeClass> obj; 
}; 

関連する問題