我有一个只包含命名空间的头文件
namespace XYZ
{
void setName(const char* name);
const char* getName();
}
源文件:
static std::string Name;
void XYZ::setName(const char* name)
{
Name.assign(name);
}
const char* XYZ::getName()
{
return Name.c_str();
}
现在,我不确定,Name
初始化时。
如果在getName()
之前调用setName()
,那么我会崩溃吗?
根据我对C ++的理解,如果在cpp文件中调用任何函数,那么将首先初始化文件中声明的静态变量。
在.cpp而不是标题中声明它的原因是降低其可见性。
答案 0 :(得分:4)
在命名空间级别定义的对象在输入main
之前以某种未指定的顺序创建。唯一的保证是,如果对象a
位于特定编译单元中的对象b
之前,则a
将在b
之前初始化。关于在不同编译单元中初始化顶级对象,不提供任何类型的保证。
如果有人在getName
之前调用setName
,如果在main
输入后发生这种情况,那么从低级别角度来看,代码是安全的,即使当然是字符串的内容将为空,因此从逻辑的角度来看,它可能是安全的,也可能是不安全的。
但是,如果您在初始化另一个全局对象期间访问getName
甚至setName
,则所有投注都会关闭,因为您甚至不允许分配给尚未构造的对象。
如果您真的需要这种预处理复杂处理,那么解决方案就是使用局部静态,例如:
std::string& theString() {
static std::string s;
return s;
}
const char *getName() {
return theString().c_str();
}
void setName(const char *s) {
theString() = s;
}
这保证是安全的,因为本地静态是在第一次输入范围时初始化(即第一次调用theString()
时),即使在进入main
之前发生这种情况。
但是根据我的经验,最好在输入main
之前尽量避免任何复杂的处理,尤其要避免任何因任何原因导致失败的问题(即访问文件或网络),因为调试变得更加困难,同样适用于在main
结束后发生的处理(即在静态持续时间对象的析构函数中)。
在运行时启动/关闭的这两个“灰色区域”中编程可能变得非常困难,因为有时甚至像调试器这样的工具也无法正常工作。
答案 1 :(得分:1)
我相信“全局”构造函数在进入“main”之前执行。如果创建了几个“全局”或“静态”对象构造函数(在单独的.cpp文件中),则无法保证其构造函数执行顺序为AFAIK。