2016-11-09 8 views
2

unique_ptrrelease()のアナログがstd::vector<>の場合、私は自分自身を見つけました。例:なぜstd :: vectorにリリースメソッドがないのですか?

std::vector<int> v(SOME_SIZE); 

//.. performing operations on v 

int* data = v.release(); // v.size() is now 0 and the ownership of the internal array is released 
functionUsingAndInternallyDeletingRowPointer(data); 

このような可能性がある特定の理由はありますか?それはstd::vectorの内部実装にいくつかの制約を課すことがありますか?

これを達成する方法がありますか、私は恥ずかしがっていないのですか?

+0

なぜでしょうか?そんなことがあると思うなら、おそらくC++委員会にロビーを立てるかもしれない。彼らは通常、コア容器に無意味なフリルを追加することに反対していることを覚えておいてください。単純に 'std :: vector'オブジェクトを削除して再作成しないのはなぜですか?私はあなたが 'release'を実装することがきわめて重要でないことが分かると思います。 – tadman

+0

あなたの例はあまりにも単純すぎます。あなたはどのデストラクタを呼び出すべきかをどのように知っていますか?あなたは正しいアロケータをどのように見つけますか? –

+0

@Kerrek SBはい、私はこのような種類の問題を考えていましたが、その点を正確に見ることはできません。 'std :: vector'は簡単な' delete [] 'ができないように破壊を扱いますか? –

答えて

1

を期待していなかったアロケータを持つベクトルへのポインタを渡された場合、あなたの関数が未定義の動作を起動する可能性があることは、STDにいくつかの制約を課すことができる::ベクトルは、内部実装ですか?ここで

もののいくつかの例では、これはと競合することが可能ということである。これらは呼び出しますので、

特殊なケースがなければ
  • 、根本的なメモリ割り当ては、new T[]によって得られず、またdelete[]によって破壊することはできません実際にはタイプTのオブジェクトは含まれていないが、割り当てられているメモリ上のコンストラクタとデストラクタ
  • 配列の先頭は実際にはメモリ割り当ての開始ではないかもしれません。例えばベクトルは配列の開始の直前に簿記情報を格納する可能性があります。
  • vector実際には破壊されてもメモリを解放しない可能性があります。例えば代わりに、小さなベクトルを素早く作成して破壊するために実装が使用する小さな配列のプールから割り当てを行うことができます。 (さらに、これらの配列はすべてちょうど大きな配列のスライスであるかもしれない)
+0

ありがとう、特にあなたの最初の点です。それは今明らかです。 –

+0

"割り当ては小規模な配列のプールから来るかもしれません" *型がmutexを非常に頻繁にロックしない限り、スレッド保証を破るでしょう。 –

+0

@ニコル:え?私は、構築、破壊、およびサイズ変更以外のものが同期を必要とする可能性があるとは考えていません。ベクタがアロケータに常に遅れていれば...それは、スレッド保証を管理しなければならない別のソフトウェアコンポーネントに問題を渡すだけです。 – Hurkyl

3

functionUsingAndInternallyDeletingRowPointer

そして、この関数は正確に何をしますか?そのメモリはstd::allocator_traits<std::allocator<T>>::allocateを呼び出すことによって割り当てられたため、std::allocator_traits<std::allocator<T>>::deallocateを呼び出すことによってメモリが削除されることが予想されます。さらに、vectorの各要素はstd::allocator_traits<std::allocator<T>>::constructを呼び出して構築されていたため、std::allocator_traits<std::allocator<T>>::destructを呼び出すことで破棄する必要があります。

この関数がポインタ上でdelete []を実行しようとすると、機能しません。あるいは、少なくともが必要ではありません。が必要です。

vectorからメモリバッファを抽出して直接使用することは合理的かもしれません。しかしそれは単なるポインタではありません。それに沿ってアロケータが必要です。

+0

ありがとう、これはまさに私です思案していた。割り振り/割り当て解除は、 'std :: vector'の内部では簡単ではありません。 –

2

私は考えることができる2つの理由があります。

  1. もともとは(前のC++ 11)、vectorは小さなオブジェクトの最適化に対応していました。つまり、サイズが十分に小さい場合は、それ自体を指摘できた可能性があります。これはC++ 11で不用意に無効にされました(vectorの移動セマンティクスは参照/イテレータの無効化を禁じています)が、将来の標準では修正される可能性があります。だから、それを歴史的に提供する理由はなく、今後はないだろう。
  2. アロケータ。それは
1

これはN4359で提案されているが、それは間違った行動(主に関連を避けるために、発信者の負担を置いて、いくつかの微妙な問題があるが判明しました。アロケータには、それは思われる)。困難と可能な選択肢については、hereを参照してください。それは最終的にC++標準化団体によって拒否されました。さらなる議論は、コメントthis questionとその回答に記載されています。

関連する問題