C ++ static const变量和销毁

时间:2009-06-19 12:41:34

标签: c++ const static-members

我遇到了一个简单的C ++类的奇怪行为。

classA.h

class A
{
public:
  A();
  ~A();
  static const std::string CONST_STR;
};

classA.cpp

#include "classA.h"
#include <cassert>

const std::string A::CONST_STR("some text");

A::A()
{
  assert(!CONST_STR.empty()); //OK
}

A::~A()
{
  assert(!CONST_STR.empty()); //fails
}

的main.cpp

#include <memory>  
#include <classA.h>  

std::auto_ptr<A> g_aStuff; 

int main() 
{ 
  //do something ... 
  g_aStuff = std::auto_ptr<A>(new A()); 
  //do something ... 
  return 0; 
}

我希望访问违规或类似的东西,但我永远不会期望静态const字符串的内容可能会改变。这里有没有人能够很好地解释该代码中会发生什么?

感谢, 诺贝特

7 个答案:

答案 0 :(得分:3)

编辑:显然,丢失的A::是代码原始帖子中的拼写错误。

原始答案:

你的意思是


    const std::string A::CONST_STR("some text");

这样CONST_STR就是类A的一部分?

否则,您将单独声明它并且初始化A的静态成员。

答案 1 :(得分:2)

您在两个不同的编译单元中创建了2个静态变量。无法判断它们的初始化顺序。但是他们的析构函数总是以相反的顺序调用。

在您的情况下,似乎发生了下一个场景:

g_aStuff constructor 
CONST_STR constructor

main funciton initializes g_aStuff

CONST_str destructor 
g_aStuff descrutor  

此时CONST_STR.empty()的结果未定义。这可能会触发断言。

答案 2 :(得分:2)

  

我希望访问违规或   类似的东西,但我永远不会想到   那个静态const的内容   字符串可能会改变。

未定义的行为:未定义。如果CONST_STR已被销毁,那么如果您访问它,则无法保证硬件异常。它可能会崩溃,但是它的地址可能会最终包含看起来像空字符串的数据:它的析构函数可能会清除指针或其他内容。

在这种情况下,您说A实例也存储在全局智能指针中,该指针在main()中指定。所以CONST_STR是在A构造函数中访问时构造的,但很可能在智能指针被销毁之前被销毁。我们需要整个计划肯定地说。

[编辑:你做到了。由于CONST_STR和g_aStuff是在不同的编译单元中定义的,因此它们的相对构造顺序不是由标准定义的。我猜测CONST_STR首先被销毁。]

答案 3 :(得分:1)

classA.cpp中定义的

const std::string CONST_STR("some text");
不是A的成员。该定义如下所示:

const std::string A::CONST_STR("some text");

答案 4 :(得分:1)

标准未指定不同翻译单元中全局/静态对象的初始化顺序。但是,它确保在执行该翻译单元的任何功能之前初始化每个这样的对象。

在你的情况下,CONST_STRg_aStuff之后被初始化,并且由于破坏的顺序与构造顺序相反,它在它之前被销毁。因此,从CONST_STR的析构函数访问A会调用未定义的行为 - 您可能会遇到访问冲突,或者您可能没有。

然而,

CONST_STRA的构造函数执行之前被初始化,因为它们位于相同的翻译单元中。

答案 5 :(得分:0)

如果存在A的全局实例(或类型A的静态类成员),则可能会发生这种情况。由于没有定义全局变量和静态的初始化顺序(交叉翻译单位),它可以是。

答案 6 :(得分:0)

查看完整代码,您将依赖于编译单元(classA.cpp和main.cpp)的销毁顺序。如果你在main中创建g_aStuff作为本地,你的断言应该通过。