OK、これ以上のコードがなければ、これはかなり一般的なものになります。これらはガイドライン (ルールではありません) であり、最も優先度の高いものが最初になります。
最初に、C++11 に関する簡単なメモ: 持っていない場合は、std::unique_ptr
以下をstd::auto_ptr
(理由により非推奨になっているため注意してください) に置き換えるか、代わりにboost::scoped_ptrを使用してください。
1.使わないnew
(単一の)山を作成する必要があり、それが宣言されているスコープ外で存続させる必要がない場合は、自動スコープで通常の変数として使用してください。
void automatic_scope(int size, double seed)
{
Mountain hill(size, Utils::powerOf2Log2(size) - 6, 0.5f, seed);
// ... mountainous operations happen here ...
} // hill is destroyed here - is that ok for you?
同様に、山が単一の ChannelClassを所有し、それを所有する山とまったく同じくらい存続する必要がある場合は、次のようにします。
class Mountain
{
ChannelClass channel;
public:
Mountain(int size, int powerthing, double something, double seed)
: channel(size, size) // initialize other members here
{
// any more initialization
}
ChannelClass& toChannel() { return channel; }
};
これで、ChannelClass
は とまったく同じように存続しMountain
、すべてが自動的に破棄され、明示的なシャットダウンは不要になります。
2.使用しないでくださいnew[]
同様に、範囲が限定された複数の山が必要な場合は、
void automatic_scope_vector(int size, double seed)
{
std::vector<Mountain> hills;
hills.push_back(Mountain(size, Utils::powerOf2Log2(size) - 6, 0.5f, seed));
// ... mountainous operations happen here ...
} // hills are all destroyed here
3. よし、new
やっぱり使う
明らかに、new を使用する正当な理由があります。その 1 つは既に言及されています (山を作成したブロックよりも長く維持する必要があります)。
もう 1 つは、実行時のポリモーフィズムが必要な場合です。たとえば、Mountain
またはのサブクラスが複数あるChannelClass
が、基本クラスを扱いたい場合です。
ポリモーフィック ファクトリ関数で両方を説明できます。
class Molehill: public Mountain { ... };
class Volcano: public Mountain { ... };
std::unique_ptr<Mountain> make_mountain(int size, double seed, bool is_molehill)
{
std::unique_ptr<Mountain> result;
if (is_molehill)
result.reset(new Molehill(size, size/2, 0.01f, seed));
else
result.reset(new Volcano(size, size*2, 0.5f, seed));
return result;
}
void automatic_scope_polymorphic(int size, double seed, bool is_molehill)
{
std::unique_ptr<Mountain> hill = make_mountain(size, seed, is_molehill);
// ... polymorphic mountainous operations happen here ...
} // hill is destroyed here unless we gave the unique_ptr to someone else
同様に、山を動的に作成ChannelClass
する必要がある場合は、それをunique_ptr
.
オブジェクトをコピーして渡す必要があり、コピーに非常にコストがかかり、RVO や移動セマンティクスに依存できない (またはまだ持っていない) 場合にも役立つ場合があります。ただし、これは最適化であるため、プロファイリングで問題が示されない限り、心配する必要はありません。
哲学
これらの C++ イディオムはすべて決定論的破壊に基づいており、明示的なクリーンアップ コードの記述をまったく回避することが目標です。
メモリー管理をコンテナー ( などstd::vector
) およびスマート・ポインター ( などstd::unique_ptr
) に委譲することで、Java がガーベッジ・コレクションで対処するメモリー・リークを回避できます。ただし、同様の自動スコープ ガード オブジェクトがメモリだけでなくすべてのリソースの管理を自動化できるRAIIに強力に一般化されます。たとえば、関数に複数の戻りパスがあり、例外がスローされる可能性がある場合でも、mutex ロックが正しく解放されるようにします。std::lock_guard
明示的なクリーンアップ コードを記述する必要がある場合: 呼び出さなければならないカスタム シャットダウン メソッドを記述しないでください。それをdestructorに入れるだけです。可能であれば、これを低レベルのガード オブジェクトにもプッシュします。