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

jac*_*bsa 3 c++ one-definition-rule linkage language-lawyer c++17

如果我有一个foo.h包含的标题

#ifndef FOO_H_
#define FOO_H_

namespace foo {
constexpr std::string_view kSomeString = "blah";
}

#endif  // FOO_H_
Run Code Online (Sandbox Code Playgroud)

那么在单个程序中包含foo.h多个.cc文件是否安全,无论它们对符号做什么kSomeString,或者是否存在可能导致ODR违规的一些用途?

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

如果可能的话,我想特别引用C++标准中的措辞.谢谢!

Bri*_*ian 7

仅包括foo.h来自多个翻译单位的内容不会违反ODR.但实际上,有一些用途kSomeString会违反ODR.有关详细信息和标准措辞,请参阅此处:https://stackoverflow.com/a/34446445

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

评估字符串文字会产生具有静态存储持续时间的字符串文字对象,从上面指定的给定字符初始化.是否所有字符串文字都是不同的(即,存储在非重叠对象中)以及是否对字符串文字的连续评估产生相同或不同的对象是未指定的.[  注意:尝试修改字符串文字的效果未定义.- 结束说明  ]

在C++ 17中,可以通过定义kSomeString来防止潜在的ODR违规inline.这将使它具有外部链接,因此在整个程序中都有一个地址(参见[basic.link]/3[basic.link]/4)并允许它进行多重定义(参见[basic.def.odr]/4).显然,.data()只能返回一个可能的值.