私は、関数を早期に終了させる可能性のある多くの障害点があるコードのセクションに取り組んでいます。私が操作しているライブラリでは、Cスタイルの配列を関数に渡す必要があります。したがって、すべての出口点で配列に対してdeleteを呼び出す代わりに、次のようにします。
void SomeFunction(int arrayLength)
{
shared_ptr<char> raiiArray(new char[arrayLength]);
pArray = raiiArray.get();
if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }
//etc.
}
unique_ptr
を使用したかったのですが、現在のコンパイラはそれをサポートしておらず、この場合、参照カウントのオーバーヘッドは実際には問題になりません。
レガシーコードとやり取りするときに、このプラクティスについて誰かが何か考えを持っているかどうか疑問に思っています。
[〜#〜] update [〜#〜]shared_ptr
の代わりにdelete
を呼び出すdelete []
を完全に忘れました。メモリリークは見られなかったので、それを使用することにしました。ベクトルを使うことすら考えていませんでした。最近、新しい(私にとって)C++を調べているので、「持っているツールがハンマーだけだと、すべてが釘のように見える」というケースがあると思います。症候群。フィードバックをお寄せいただきありがとうございます。
PDATE2質問を変更し、同じ間違いを犯した人にとってもう少し価値のあるものにするための回答を提供すると思いました。 scoped_array
、shared_array
、vector
のような選択肢がありますが、shared_ptr
を使用して配列のスコープを管理できます(ただし、この後、なぜそうするのかわかりません。をしたい):
template <typename T>
class ArrayDeleter
{
public:
void operator () (T* d) const
{
delete [] d;
}
};
void SomeFunction(int arrayLength)
{
shared_ptr<char> raiiArray(new char[arrayLength], ArrayDeleter<char>());
pArray = raiiArray.get();
if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }
//etc.
}
動的に割り当てられた配列へのポインタを保持するためにshared_ptr
またはscoped_ptr
を使用しないでください。 shared_ptrとscoped_ptrは、delete ptr;
を使用して、ポインターが参照されなくなったとき/スコープから外れたときにクリーンアップします。これにより、動的に割り当てられた配列で未定義の動作が呼び出されました。代わりに、shared_arrayまたはscoped_arrayを使用してください。これらは、破棄するときにdelete[] ptr;
を正しく使用します。
質問に答えるには、スマートポインターを渡さない場合は、scoped_array
よりもオーバーヘッドが少ないため、shared_array
を使用します。
または、配列ストレージとしてstd::vector
を使用します(ベクトルは連続したメモリ割り当てを保証しています)。
使用する boost::scoped_array
、またはさらに良いstd::vector
配列を扱っている場合。
単にstd::vector
を使用することを強くお勧めします。 vectors
の要素はヒープに割り当てられ、関数を終了する場所でvector
がスコープ外になると削除されます。
vector
をCスタイルの配列を必要とするレガシーコードに渡すには、単に&vectorName[0]
を渡します。要素はメモリ内で連続していることが保証されています。
C++ 11ユーザー向けの注意事項:
shared_ptr
の場合、C++ 11には、<memory>
で定義され、標準に準拠した(最終ドラフトでの)配列型のデフォルトの削除機能があるため、次のような場合に追加の派手な削除機能なしで使用できます。
std::shared_ptr<char> raiiArray(new char[arrayLength], std::default_delete<char[]>());
C++ 11のunique_ptr
には、new[]
およびdelete[]
を処理するための部分的な特殊化があります。しかし、残念ながら、共通の動作はありません。 shared_ptr
にそのような専門分野がないのには十分な理由があるはずですが、私はそれを探しませんでした。ご存知の場合は、共有してください。
boost::scoped_ptr
このため。
この
shared_ptr<char*> raiiArray(new char[arrayLength]);
これは良い習慣ではありませんが、演算子new[]
で割り当てるため、未定義の動作が発生しますが、shared_ptr
はoperator delete
を使用してメモリを解放します。使用する正しいことはboost::shared_array
であるか、カスタム削除機能を追加することです。