什么时候在命名空间的cpp文件中声明的静态字符串被初始化?

时间:2014-04-11 10:36:40

标签: c++

我有一个只包含命名空间的头文件

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而不是标题中声明它的原因是降低其可见性。

2 个答案:

答案 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。