我知道向量元素破坏顺序没有用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