When是初始化命名空间的cpp文件中声明的静态字符串

When is static string declared in cpp file of namespace initialized?

本文关键字:声明 静态 字符串 文件 cpp 初始化 命名空间 When      更新时间:2023-10-16

我有一个头文件,其中只包含一个命名空间

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何时初始化。

如果在setName()之前调用getName(),那么我会崩溃吗??

根据我对C++的理解,如果在cpp文件中调用任何函数,那么文件中声明的静态变量将首先初始化。

在.cpp而不是头中声明它的原因是为了降低它的可见性。

在输入main之前,在命名空间级别定义的对象将以某种未指定的顺序创建。唯一的保证是,如果对象a在特定编译单元中位于对象b之前,则a将在b之前初始化。对于不同编译单元中的顶级对象的初始化,没有提供任何形式的保证。

在您的情况下,如果有人在setName之前调用getName,则从低级角度来看,代码是安全的,前提是这发生在输入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结束后发生的处理(即在静态持续时间对象的析构函数中)。

在运行时启动/关闭的这两个"灰色地带"中编程可能会变得非常困难,因为有时甚至像调试器这样的工具也无法正常工作。

我相信"global"构造函数是在进入"main"之前执行的。如果创建了几个"全局"或"静态"对象构造函数(在单独的.cpp文件中),则不能保证它们的构造函数执行顺序为AFAIK。