【问题标题】:C++ standard: ODR and constexpr std::string_viewC++ 标准:ODR 和 constexpr std::string_view
【发布时间】:2017-08-14 00:28:21
【问题描述】:

如果我有一个标题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++ standard 中的措辞。谢谢!

【问题讨论】:

  • 这与string_view具体有什么关系?
  • 大部分问题通常是关于标题中的constexpr 声明,但在使用 C 字符串进行初始化时可能存在一些特殊问题,这些问题不适用于例如constexpr int.

标签: c++ language-lawyer c++17 linkage one-definition-rule


【解决方案1】:

仅包含来自多个翻译单元的foo.h 不会违反 ODR。然而,事实上,kSomeString 的某些用途会违反 ODR。有关详细信息和标准措辞,请参见此处:https://stackoverflow.com/a/34446445

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

评估 string-literal 会产生一个具有静态存储持续时间的字符串字面量对象,从上面指定的给定字符初始化。是否所有字符串文字都是不同的(即,存储在不重叠的对象中)以及字符串文字的连续评估是否产生相同或不同的对象是未指定的。 [ 注意: 尝试修改字符串文字的效果是不确定的。 — 尾注 ]

在 C++17 中,可以通过将 kSomeString 定义为 inline 来防止潜在的 ODR 违规。这将为其提供外部链接,从而在整个程序中提供单个地址(请参阅[basic.link]/3[basic.link]/4)并允许对其进行多重定义(请参阅[basic.def.odr]/4)。显然.data() 只能返回一个可能的值。

【讨论】:

  • 您确定在我的示例中 kSomeString 存在一些 ODR 问题吗?似乎basic.link/3.2 保证它将在所有翻译单元中具有内部链接,因为它是命名空间范围和常量。
  • (回答我自己的问题:参见this answer,它给出了一个有问题的使用示例。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-29
相关资源
最近更新 更多