벡터 요소의 파기 순서가 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();
}
OUTPUT - F2로) (F1()
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