When是初始化命名空间的cpp文件中声明的静态字符串
When is static string declared in cpp file of namespace initialized?
我有一个头文件,其中只包含一个命名空间
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。
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 如何在C++函数中声明静态 2D 数组?
- 无法声明静态 constexpr char []
- 缺少类型说明符 - int 假定 声明静态成员后出错
- 如何在类中声明静态 const 结构元素
- 如何在C++中嵌套词法作用域可访问的作用域中声明静态信息?
- 为什么我不能使用 msvc 在模板类中声明静态 constexpr 变量?
- 在 C++14 中使用 decltype(auto) 声明静态数据成员
- 重新声明静态 constexpr 数据成员?
- 如何在C++中声明静态常量结构
- 声明静态对象和指向静态对象的指针之间的区别
- C++在类中声明静态枚举与枚举
- 声明"静态常量"和"常量静态"有什么区别
- "Undefined reference"声明C++静态成员变量
- C++ 在声明静态成员时是否创建实例
- 在c++11中使用可变大小声明静态数组
- 我们如何能够在与类具有相同数据类型的类中声明静态成员
- 为什么在c++中声明静态成员会导致链接器链接atexit
- 在对象是静态的类函数中声明静态变量是否有意义
- 在C++中声明静态/动态数组会自动调用每个元素的默认构造函数