C++;静态常量变量与销毁 我遇到了一个简单的C++类的奇怪行为。< /P>

C++;静态常量变量与销毁 我遇到了一个简单的C++类的奇怪行为。< /P>,c++,constants,static-members,C++,Constants,Static Members,A.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(!

A.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
}
#包括“classA.h”
#包括
const std::string A::const_STR(“一些文本”);
A::A()
{
断言(!CONST_STR.empty());//确定
}
A::~A()
{
断言(!CONST_STR.empty());//失败
}
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; 
}
#包括
#包括
std::自动ptr g_aStuff;
int main()
{ 
//做点什么。。。
g_aStuff=std::auto_ptr(新的A());
//做点什么。。。
返回0;
}
我期望访问冲突或任何类似的情况,但我从未期望静态常量字符串的内容会改变。这里有人能很好地解释代码中发生了什么吗

谢谢,
Norbert

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

编辑:显然,缺少的
A::
是代码原始帖子中的一个输入错误

原始答复:

你的意思是


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

const std::string A::const_STR(“一些文本”);
因此CONST_STR是类
A
的一部分

否则,您将单独声明它,而不是初始化
A

编辑的静态成员:显然,缺少的
A::
是代码原始帖子中的一个输入错误

原始答复:

你的意思是


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

const std::string A::const_STR(“一些文本”);
因此CONST_STR是类
A
的一部分

否则,您将单独声明它,而不是初始化
A

的静态成员。在classA.cpp中定义的不是A的成员。该定义如下所示:

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

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

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

在您的案例中,似乎发生了下一个场景:

g_aStuff constructor 
CONST_STR constructor

main funciton initializes g_aStuff

CONST_str destructor 
g_aStuff descrutor  

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

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

在您的案例中,似乎发生了下一个场景:

g_aStuff constructor 
CONST_STR constructor

main funciton initializes g_aStuff

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

我希望访问权限被侵犯或者 类似的事情,但我从来没想过 静态常量的内容 字符串可能会改变

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

在本例中,您可以说A实例也存储在全局智能指针中,该指针在main()中分配。因此,CONST_STR是在构造函数中访问时构造的,但很可能在智能指针被销毁之前就被销毁了。我们需要整个计划来确定

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

我希望访问权限被侵犯或者 类似的事情,但我从来没想过 静态常量的内容 字符串可能会改变

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

在本例中,您可以说A实例也存储在全局智能指针中,该指针在main()中分配。因此,CONST_STR是在构造函数中访问时构造的,但很可能在智能指针被销毁之前就被销毁了。我们需要整个计划来确定


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

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

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

该标准没有指定不同转换单元中全局/静态对象的初始化顺序。但是,它保证在执行该转换单元的任何功能之前初始化每个此类对象

在您的例子中,恰好
CONST_STR
g_aStuff
之后初始化,并且由于销毁顺序与构造顺序相反,它在它之前被销毁。因此,从
A
的析构函数访问
CONST_STR
会调用未定义的行为-您可能会遇到访问冲突,或者您可能会遇到可能不会


然而,
CONST_STR
是在执行
构造函数之前初始化的,因为它们在同一个翻译单元中。

该标准没有指定初始值的顺序