C++ 命名空间中的常量全局变量
我知道C++ 命名空间中的常量全局变量,c++,C++,我知道staticconstclass成员只能在标题中初始化。名称空间也是这样吗?例如,写入以下内容是否有效: namehman.hpp namespace namehuman { string const human("human"); } #include "namehuman.hpp" cout << namehuman::human << endl; main.cpp namespace namehuman { string const human
static
const
class
成员只能在标题中初始化。名称空间也是这样吗?例如,写入以下内容是否有效:
namehman.hpp
namespace namehuman
{
string const human("human");
}
#include "namehuman.hpp"
cout << namehuman::human << endl;
main.cpp
namespace namehuman
{
string const human("human");
}
#include "namehuman.hpp"
cout << namehuman::human << endl;
#包括“namehuman.hpp”
cout常数具有内部链接。因此,任何包含带有常量定义的头的编译单元都将拥有自己的对象实例
根据C++标准(3.5程序和链接)< /P>
3具有名称空间作用域(3.3.6)的名称在以下情况下具有内部链接:
姓名
-显式声明为const或const的非易失性变量
constexpr,既没有显式声明extern,也没有先前声明
宣布有外部联系;或
如果您想要一个带有外部链接的常量,则必须使用说明符extern
声明它,并在编译单元中定义它。我认为这将多次定义human
,因此可能会导致ODR冲突(见下文)。通常最好只在标题中声明它
extern const string human;
并将定义添加到实现文件中
string human("human");
关闭应用程序时,请小心初始化顺序失败和类似情况
当带有外部链接ODR的内联函数使用human
时,可能会导致ODR冲突。我认为,因为这很容易做到,而且没有办法防止它,所以最好在实现文件中定义常量字符串。尽管将多次定义human
,但这不是ODR冲突,因为定义具有内部链接。您建议的更改,不清楚是否是改进,甚至可能会减慢代码的速度;弗洛里安,因为虽然你的代码“有效”,但这是一个错误的答案(顺便说一句,我没有投反对票)。请看另一个答案。我说过这可能会导致ODR冲突:如果内联函数访问存储在human
中的字符串,则使用ODR,但如果使用ODR,则要求只有一个定义。这不会导致ODR冲突。每个翻译单元的人
是一个不同的对象,每个这样的对象只有一个定义。(参见[basic.link]/2,内部链接的定义是其他单位的名称不能引用它)@M.M,这正是问题所在。如果内联函数根据转换单元使用不同的对象,则会出现ODR冲突。(请参见[basic.dev.odr]/3,每个程序应包含该程序中使用的每个非内联函数或变量的一个定义。)