C++;静态常量变量与销毁 我遇到了一个简单的C++类的奇怪行为。< /P>
A.h级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(!
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
是在执行构造函数之前初始化的,因为它们在同一个翻译单元中。该标准没有指定初始值的顺序