本文介绍了为什么这些函数局部静态对象的销毁顺序不是它们的初始化顺序的倒数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我有两个函数本地静态对象,一和二。一个构造函数和析构函数都通过GetTwo()访问两个: #include< iostream> struct One; struct Two; const One&得到一个(); const Two& getTwo(); struct Two { const char * value =这是两个! Two(){std :: cout<< 两构建体<< std :: endl; } 〜Two(){std :: cout<< Two destruct<< std :: endl; } }; struct One { One(){ std :: cout< 一个构建体< std :: endl; const char * twoval = GetTwo()。value; std :: cout<< twoval is:< twoval<< std :: endl; } 〜One(){ std :: cout< 一个破坏< std :: endl; const char * twoval = GetTwo()。value; std :: cout<< twoval is:< twoval<< std :: endl; } }; const One& GetOne(){ static一个; return one; } const Two& GetTwo(){ static两个; return two; } int main(void){ GetOne(); } 我用g ++ 4.8.4编译: g ++ -std = c ++ 11 [filename] 并输出: 一个构造两个构造 twoval是:这是两个! 一个破坏 twoval是:这是两个! 两个破坏 它们以相同的顺序构造和破坏!我读到在同一翻译单元中的C ++类的静态变量,破坏的顺序总是与构造的顺序的逆。但我猜不是?或者,这是未定义的行为吗? 此外,我听说对于C ++ 11,C ++委员会添加了一些花哨的保证函数本地静态变量, 。如果没有定义,那么这种行为是这些保证的一部分吗? (这将是相当不错,因为它会阻止你使用一个破坏的二的实例的One的析构器射击自己。)如果GetOne和GetTwo是在不同的翻译单位,如何保证? 感谢你的评论到目前为止,我现在看到一个对象被认为是构造函数返回后,而不是当它被认为是构造函数。首先输入,因此Two实际上是在一个之前构建的。 同时我试图阅读标准,并在C ++ 11标准的第6.7节第4项:破坏,6.7点我们到3.6.3,它说:在您的代码中,两个 一个。因此两个的构造函数的完成是在一个的构造函数完成之前排序的 因此, one 的析构函数的完成在 two ,这说明您看到的内容。 I have two function-local static objects, One and Two. One's constructor and destructor both access Two through GetTwo():#include <iostream>struct One;struct Two;const One& GetOne();const Two& GetTwo();struct Two { const char* value = "It's two!"; Two() { std::cout << "Two construct" << std::endl; } ~Two() { std::cout << "Two destruct" << std::endl; }};struct One { One() { std::cout << "One construct" << std::endl; const char* twoval = GetTwo().value; std::cout << "twoval is: " << twoval << std::endl; } ~One() { std::cout << "One destruct" << std::endl; const char* twoval = GetTwo().value; std::cout << "twoval is: " << twoval << std::endl; }};const One& GetOne() { static One one; return one;}const Two& GetTwo() { static Two two; return two;}int main(void) { GetOne();}I compile this with g++ 4.8.4: g++ -std=c++11 [filename]And it outputs:One constructTwo constructtwoval is: It's two!One destructtwoval is: It's two!Two destructThey are constructed and destructed in the same order! I read that for static variables of C++ classes in the same translation unit, the order of destruction is always the inverse of the order of construction. But I guess not? Or, is this undefined behavior?Also, I heard that for C++11, the C++ committee added some fancy guarantees for function-local static variables, like thread safety. If not undefined, then is this behavior a part of those guarantees? (Which would be pretty nice, since it would stop you from shooting yourself in the foot with One's destructor using a destructed instance of Two.) And what's guaranteed if GetOne and GetTwo are in different translation units?EDIT:Thanks for the comments so far, I see now that an object is considered constructed only after its constructor returns, not when it is first entered, so Two is actually constructed before One.Also I've attempted to read the standard and found this in the C++11 standard, section 6.7 item 4:And for destruction, 6.7 points us to 3.6.3, which says:So if I'm reading this right: For function-local static objects, their construction is "sequenced" at runtime, based on the order the functions are called. And, no matter what translation unit they are defined in, they will be destructed in the inverse of that runtime-dependent order.Does this sound right? That would make this a nice solution to the static order initialization fiasco. That said, I think you could still shoot yourself in the foot with the code below:#include <iostream>struct One;struct Two;const One& GetOne();const Two& GetTwo();void PrintOneValue(const One& one);struct Two { Two() { std::cout << "Two construct" << std::endl; } ~Two() { std::cout << "start Two destruct" << std::endl; PrintOneValue(GetOne()); std::cout << "end Two destruct" << std::endl; }};struct One { const char* value = "It's one!"; One() { std::cout << "start One construct" << std::endl; GetTwo(); std::cout << "end One construct" << std::endl; } ~One() { std::cout << "One destruct" << std::endl; }};void PrintOneValue(const One& one) { std::cout << "One's value is: " << one.value << std::endl;}const One& GetOne() { static One one; return one;}const Two& GetTwo() { static Two two; return two;}int main(void) { GetOne();}Which outputs:start One constructTwo constructend One constructOne destructstart Two destructOne's value is: It's one!end Two destructIt accesses One's data after it is destructed, so undefined behavior. But at least it's deterministic. 解决方案 The actual Standard text in C++14 [basic.start.term] is:In your code, two is constructed during the constructor of one. Therefore the completion of constructor of two is sequenced-before the completion of constructor of one.So the completion of the destructor of one is sequenced-before the completion of the destructor of two, which explains what you are seeing. 这篇关于为什么这些函数局部静态对象的销毁顺序不是它们的初始化顺序的倒数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-21 13:32