ベクトル要素の破壊順序はC++標準では定義されていません(Order of destruction of elements of an std::vector参照)、私が調べたすべてのコンパイラが最初から最後までこの破壊を行うことがわかりました。これはダイナミックな配列と静的な配列が逆になるのでこの逆の順序はC++の世界では非常に頻繁に起こります。ベクトル要素の破壊順序を定義することは合理的でしょうか?
厳密に言うと、私は、「コンテナのメンバーは、例えば、メンバーの挿入と削除の機能を使って、どのような順序でも構築および破棄できます」と知っています。変更 "。私は、現在のベクトルデストラクタの実装を前方破壊から要素の後方破壊に変えることに投票するだけです。 C++標準にこのルールを追加することもできます。
そしてなぜですか?配列からベクトルへの変更はこのように安全です。
実際の世界の例: mutexesのロックとロック解除の順序は非常に重要です。ロック解除が確実に行われるように、ScopeGuardパターンが使用されます。それから破壊命令が重要です。この例を考えてみましょう。そこ - ベクトル原因のデッドロックへの配列からの切り替え - 彼らの破壊の順序が異なるという理由だけで:
class mutex {
public:
void lock() { cout << (void*)this << "->lock()\n"; }
void unlock() { cout << (void*)this << "->unlock()\n"; }
};
class lock {
lock(const mutex&);
public:
lock(mutex& m) : m_(&m) { m_->lock(); }
lock(lock&& o) { m_ = o.m_; o.m_ = 0; }
lock& operator = (lock&& o) {
if (&o != this) {
m_ = o.m_; o.m_ = 0;
}
return *this;
}
~lock() { if (m_) m_->unlock(); }
private:
mutex* m_;
};
mutex m1, m2, m3, m4, m5, m6;
void f1() {
cout << "f1() begin!\n";
lock ll[] = { m1, m2, m3, m4, m5 };
cout <<; "f1() end!\n";
}
void f2() {
cout << "f2() begin!\n";
vector<lock> ll;
ll.reserve(6); // note memory is reserved - no re-assigned expected!!
ll.push_back(m1);
ll.push_back(m2);
ll.push_back(m3);
ll.push_back(m4);
ll.push_back(m5);
cout << "f2() end!\n";
}
int main() {
f1();
f2();
}
をOUTPUT - f1からf2に破壊順序の変更を()(参照)
f1() begin!
0x804a854->lock()
0x804a855->lock()
0x804a856->lock()
0x804a857->lock()
0x804a858->lock()
f1() end!
0x804a858->unlock()
0x804a857->unlock()
0x804a856->unlock()
0x804a855->unlock()
0x804a854->unlock()
f2() begin!
0x804a854->lock()
0x804a855->lock()
0x804a856->lock()
0x804a857->lock()
0x804a858->lock()
f2() end!
0x804a854->unlock()
0x804a855->unlock()
0x804a856->unlock()
0x804a857->unlock()
0x804a858->unlock()
IMHOソフトウェアがうまく設計されているかどうかは、破壊の順序は関係ありません。デストラクタが呼び出されると、これはオブジェクトがもはや使用されていないか、必要でないことを意味します。オブジェクトを破壊する前に、オブジェクトが一貫した状態(この場合はもう使用されていない状態)にあることを確認する必要があります。 – m0skit0
実行の順序が重要なときには、コンテナに入れて生成されたコードを破棄することはお勧めできません。 //皮肉の告知:「私たち全員が知っている」ステートメントで少し疑わしいです。 – stefaanv
おそらくあなたは読まなくても答えました。 n ScopeGuard(http://stackoverflow.com/questions/48647/does-scopeguard-use-really-lead-to-better-code)私がここで使用したのは、破壊命令です。だから私はこの例を使ったのです。 – PiotrNycz