C++ standard: ODR and constexpr std::string_view

C++ standard: ODR and constexpr std::string_view

本文关键字:string std view and standard ODR C++ constexpr      更新时间:2023-10-16

如果我有一个foo.h包含

#ifndef FOO_H_
#define FOO_H_
namespace foo {
constexpr std::string_view kSomeString = "blah";
}
#endif  // FOO_H_

那么,在单个程序中包含多个.cc文件中的foo.h是否安全,无论它们如何处理符号kSomeString,或者是否有某些用途可能导致 ODR 违规?

此外,是否保证kSomeString.data()将在.cc文件中返回相同的指针?

如果可能的话,我希望具体引用C++标准中的措辞。谢谢!

仅包含来自多个翻译单元的foo.h不会违反 ODR。但是,确实有一些kSomeString的使用会违反ODR。有关详细信息和标准措辞,请参阅此处:https://stackoverflow.com/a/34446445

不能保证kSomeString.data()在所有翻译单元中返回相同的值,因为不能保证字符串文本"blah"在所有翻译单元中都是同一对象。根据 [lex.string]/16,

计算字符串文本

会生成具有静态存储持续时间的字符串文本对象,该对象从上面指定的给定字符初始化。是否所有字符串文本都是不同的(即,存储在非重叠对象中(,以及字符串文本的连续计算是否产生相同或不同的对象。[注意:尝试修改字符串文本的效果未定义。— 尾注]

在 C++17 中,可以通过定义要inlinekSomeString来防止潜在的 ODR 违规。这将给它外部链接,从而在整个程序中提供一个单一的地址(参见[basic.link]/3和[basic.link]/4(,并允许它被乘法定义(参见[basic.def.odr]/4(。显然,.data()只能返回一个可能的值。