我知道向量元素破壞順序沒有用C++定義的標準(見Order of destruction of elements of an std::vector),我看到了,我檢查了所有的編譯器做到這一點的破壞,從開始到結束 - 這是相當令人驚訝的我,因爲動態和靜態數組做反向順序,而這種相反的順序在C++世界中經常出現。定義向量元素的銷燬順序是否合理?
要嚴格:我知道「集裝箱會員...可以構造和使用,例如以任意順序插入銷燬和擦除成員函數」,我不選「容器保持某種日誌在這些變化」。我只是投票改變當前矢量析構函數的實現,從向前銷燬到向後銷燬元素 - 僅此而已。也許可以將此規則添加到C++標準中。
其原因爲什麼?從陣列到矢量的轉換將更安全。
現實世界的例子: 我們都知道,互斥鎖定和解鎖順序是非常重要的。並確保解鎖發生 - 使用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();
}
輸出 - 看到從破壞秩序的變化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()
恕我直言銷燬順序應該不會影響,如果軟件設計的很好。當調用析構函數時,這意味着對象不再被使用或不需要。在銷燬它們之前,你應該確保你的對象處於一致的狀態(在這種情況下不再使用)。 – m0skit0
我們也都知道,當執行順序很重要時,將它們放在任何容器中並讓生成的代碼銷燬並不是一個好主意。 //嘲諷注意:我對「我們都知道」陳述有點懷疑 – stefaanv
可能你沒有閱讀就回答。 n ScopeGuard(http://stackoverflow.com/questions/48647/does-scopeguard-use-really-lead-to-better-code)我在這裏使用的銷燬順序很重要。這就是我使用這個例子的原因。 – PiotrNycz