Global Externs。字符串和字符之间的区别*

时间:2014-07-22 10:51:43

标签: c++ string global-variables const extern

我有两个问题:

  1. 我曾经有一个包含

    的Constants.h
    const std::string PATH("/ram/")
    

    它工作正常。

    但是当我添加

    const char* BLAH = "blah";
    

    到同一个文件。我在链接期间遇到了重新定义错误。

    我知道这是因为每个编译单元都会创建自己的常量,因此这会在链接期间导致问题,但是为什么它之前的常规std :: strings不适用于char * s?

  2. 所以在第一期之后,我决定将所有内容都设置为extern,现在我有一个Constants.h和一个Constants.cpp。但后来我遇到了另一个问题。我有另一个文件Test.cpp,其中一个常量定义为

    const std::string FOO(PATH + "booyah");
    

    这用于创建“/ ram / booyah”,但现在它只是“booyah”。 PATH以某种方式变得空洞。我猜它与extern有关,并且在编译期间创建了常量。常量PATH在运行时可以正常工作。

  3. 这是正确的理解吗?有没有办法让所有这些很好地协同工作?

    提前致谢!

3 个答案:

答案 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”;