C++ 标准:ODR 和 constexpr std::string_view

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

如果我有一个 header 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() 将 return 在 .cc 个文件中使用相同的指针?

如果可能的话,我希望具体参考 C++ standard 中的措辞。谢谢!

仅包含来自多个翻译单元的 foo.h 不会违反 ODR。但是,确实,kSomeString 的某些用途会违反 ODR。有关详细信息和标准措辞,请参见此处:

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

Evaluating a string-literal results in a string literal object with static storage duration, initialized from the given characters as specified above. Whether all string literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified. [ Note: The effect of attempting to modify a string literal is undefined. — end note ]

在 C++17 中,可以通过将 kSomeString 定义为 inline 来防止潜在的 ODR 违规。这将为其提供外部链接,从而在整个程序中提供一个地址(参见 [basic.link]/3 and [basic.link]/4) and allow it to be multiply defined (see [basic.def.odr]/4)。显然 .data() 只能 return 一个可能的值。