次のものがあると仮定します。
//! SomeClass.hpp
class
{
public:
SomeClass( void );
~SomeClass( void )
{
delete mFoo;
delete mBar;
}
...
private:
Foo* mFoo;
Bar* mBar;
StackObj mStackFoo;
};
//! SomeClass.cpp
SomeClass::SomeClass( void )
{
mFoo = new Foo;
mBar = new Bar;
mStackFoo = StackObj( ... );
}
さて、ポインタを初期化すると、コンストラクタがSomeClassのメンバーの不要なコピーを作成し、メモリを割り当てるためだけにメモリを割り当ててから割り当てを解除することを理解しています。
これを回避する方法として、初期化リストを別の初期化関数(ヒープに割り当てられたメモリ用)と組み合わせて使用するのが一般的です。SaySomeClass
には、として定義されたプライベートメンバー関数がありvoid initHeapMem( void )
ます。その後、私たちはすることができます、
SomeClass::SomeClass( void )
: mFoo( NULL ),
mBar( NULL ),
mStackFoo( ... )
{
initHeapMem();
}
void SomeClass::initHeapMem( void )
{
mFoo = new Foo;
mBar = new Bar;
}
当然、これで問題はある程度解決します。ここでの問題は、実行されている別の関数呼び出しのオーバーヘッドがまだあることだと思います。
生のポインタに初期化リストを使用できない理由は、それらがスレッドセーフではないためです。何か問題が発生し、プログラムが例外をスローした場合でも、メモリリークが発生します。注:これは私が読んだ内容によるものです。これが間違っている場合はお詫びします。
したがって、boost / C ++ 11を使用する#include <tr1/memory>
と、ヘッダーファイルのディレクティブからスマートポインターを使用できます(STLを使用していると仮定)。
たとえば、を使用する場合はstd::unique_ptr< T >
、次のようBar* mBar
にFoo* mFoo
置き換えます。
std::unique_ptr< Foo > mFoo;
std::unique_ptr< Bar > mBar;
そうすれば、それが可能になります。
SomeClass::SomeClass( void )
mFoo( new Foo ),
mBar( new Bar ),
mStackFoo( ... )
{
}
スマートポインタはメモリ割り当てを独自のコンストラクタで効果的にラップするためです。
これは優れたソリューションですが、私は個人的に、作成するすべてのヒープオブジェクトにスマートポインターを使用するわけではありません。C++コミュニティには同じように感じる人がいることを知っています。
tl; dr
これらすべてが邪魔にならないので、私が本当に疑問に思っているのは、上記でリストしたものとは別に、オブジェクト内でクラスメンバーを初期化する(特にC ++ 11の出現で)より効率的な代替手段があるかどうかです。