代码之家  ›  专栏  ›  技术社区  ›  luk32

相同内容字符串文本的存储是否保证相同?

  •  24
  • luk32  · 技术社区  · 6 年前

    下面的代码安全吗?编写类似这样的代码可能很有诱惑力:

    #include <map>
    
    const std::map<const char*, int> m = {
        {"text1", 1},
        {"text2", 2}
    };
    
    int main () {
        volatile const auto a = m.at("text1");
        return 0;
    }
    

    映射仅用于字符串文本。

    我认为这是完全合法的,似乎是工作,但我从来没有看到一个保证,指针的文字使用在两个不同的地方是相同的。我无法让编译器为具有相同内容的文本生成两个单独的指针,所以我开始怀疑这个假设有多可靠。

    4 回复  |  直到 6 年前
        1
  •  19
  •   aschepler    6 年前

    该标准不保证具有相同内容的字符串文本的地址将是相同的。事实上, [lex.string]/16

    是否所有字符串文字都是不同的(即存储在不重叠的对象中),以及 串文字 未指定相同或不同的对象。

    因此,在字符串文本重复时使用相同的字符数组对象是可选的编译器优化。在安装了g++和默认编译器标志之后,我还发现在同一个翻译单元中,两个相同的字符串文字的地址是相同的。但正如您所猜测的,如果相同的字符串文本内容出现在不同的翻译单元中,我会得到不同的文本。


    const char* abcdef = "abcdef";
    const char* def = "def";
    const char* def0gh = "def\0gh";
    

    你可能会发现 abcdef+3 , def ,和 def0gh 都是同一个指针。

    此外,有关重用或重叠字符串文字对象的规则仅适用于与文字直接关联的未命名数组对象,如果文字立即衰减为指针或绑定到对数组的引用时使用。还可以使用文本初始化命名数组,如中所示

    const char a1[] = "XYZ";
    const char a2[] = "XYZ";
    const char a3[] = "Z";
    

    这里是数组对象 a1 , a2 a3 使用文字初始化,但被视为与实际文字存储不同(如果存在这样的存储),并遵循普通对象规则,因此这些数组的存储不会重叠。

        2
  •  20
  •   StoryTeller - Unslander Monica    6 年前

    两个内容完全相同的字符串文字是否是完全相同的对象,这是未指明的,在我看来最好不要依赖。引用标准:

    16 计算字符串文字将生成字符串文字对象 如上所述。是否所有字符串文字都是不同的(即, 对字符串文本的求值产生相同或不同的对象 未指定。

    std::string ,可以编写简单的视图类型(或使用 std::string_view

        3
  •  5
  •   Bathsheba    6 年前

    不,C++标准没有这样的保证。

    也就是说,如果代码在同一个翻译单元中,那么就很难找到反例。如果 main() 如果是另一种翻译,那么反例可能更容易产生。

    这个 volatile 限定符是一条红鲱鱼。

        4
  •  3
  •   Maxim Egorushkin    6 年前

    C++标准不需要实现对字符串字符串的反复制。

    当字符串文本驻留在另一个翻译单元或另一个需要链接器的共享库中时( ld )或运行时链接器( ld.so