我有两个问题:
我曾经有一个包含
的Constants.hconst std::string PATH("/ram/")
它工作正常。
但是当我添加
时const char* BLAH = "blah";
到同一个文件。我在链接期间遇到了重新定义错误。
我知道这是因为每个编译单元都会创建自己的常量,因此这会在链接期间导致问题,但是为什么它之前的常规std :: strings不适用于char * s?
所以在第一期之后,我决定将所有内容都设置为extern,现在我有一个Constants.h和一个Constants.cpp。但后来我遇到了另一个问题。我有另一个文件Test.cpp,其中一个常量定义为
const std::string FOO(PATH + "booyah");
这用于创建“/ ram / booyah”,但现在它只是“booyah”。 PATH
以某种方式变得空洞。我猜它与extern有关,并且在编译期间创建了常量。常量PATH
在运行时可以正常工作。
这是正确的理解吗?有没有办法让所有这些很好地协同工作?
提前致谢!
答案 0 :(得分:2)
当某些内容为const
时,会自动生成static
内部链接。
因此,当您有const std::string
时,它实际上是static const std::string
。
这意味着每个编译单元都会获得自己的字符串副本,这会浪费内存,但通常不是一个大问题。
要解决此问题,请在标头文件中设置extern const std::string s;
,在源文件中设置extern const std::string s = "..";
。
为了避免需要源文件,您可以尝试使用此替代方法,尽管编译可能会更长。它也只会分配一次字符串。
inline const std::string& GetStr()
{
static const std::string s = "..";
return s;
}
现在,为什么没有const char* BLAH
在标题中编译?这是因为BLAH不是常数。虽然它是一个只读指针,但指针不是常量,可以改为指向别的东西。
要像使用const std::string
一样编译代码,必须使用const char *const BLAH = "..";
。现在它是一个真正的常量,将编译为static
。这也遇到了每个编译单元接收指针副本的相同问题。它还可能会收到字符串文字的副本,具体取决于编译器优化。您可以使用上面的extern
方法解决此问题。
在同一编译单元中初始化常量的顺序是它们出现的顺序。但是,未定义在编译单元之间初始化常量的顺序。这意味着来自一个源文件的extern
不应该依赖于来自其他源文件的extern
。
您可以通过以正确的顺序在同一源文件中定义所有常量,或使用函数(可能inline
)来返回字符串来解决此问题。
答案 1 :(得分:1)
const
的全局变量具有内部链接。您的BLAH
变量不是const
,因此默认为外部链接。您可以将其声明为static
,也可以将其设为const
:
const char * const BLAH = "blah";
如果你发现很难在C ++中拼写类型名称,你可以使用类型别名来让你的生活更轻松:
using ccp = const char *;
const std::string foo = "foo";
const ccp bar = "bar";
答案 2 :(得分:0)
由于头文件可以包含在多个CPP文件中,因此会出现冲突。您可以使用static关键字。
我通常这样做:static const char * const str =“blah”;