即使读完之后这个关于非显式内联命名空间作用域变量的问题 https://stackoverflow.com/q/46107312/3537677,在标头中定义,我对显式内联名称空间作用域变量是否可以有点偏执,因为据我所知,违反 ODR 的行为是 UB 并且不需要诊断。我的理解是否正确,明确内联指定constexpr
(and const
非易失性类似)在命名空间范围内定义的变量是内联变量因此,当在不同的翻译单元中使用时,它们的 ODR 用法是否可以?
甚至 cppreference.com 也自相矛盾,有时它说内联变量必须是外部的,才能实现 ODR 使用异常,而在另一个页面上,一般来说只有内部链接内联变量是可以的,只有在有额外要求的情况下才可以使用外部变量。
这些假设基本上正确吗?:
/*! @file some_header.hpp */
#ifndef HEADER_GUARD
#define HEADER_GUARD
constexpr int global_non_expl_inline = 42; //UB
static constexpr int global_non_expl_inline_static = 42; //UB
inline int global_expl_inline = 42; //ok
inline int static global_expl_inline_explicit_static = 42; //? external linkage by default but static explicit but still ok?
inline int extern global_expl_inline_explicit_extern = 42; //UB
namespace foo {
constexpr int global_non_expl_inline = 42; //UB
static constexpr int global_non_expl_inline_static = 42; //UB
inline int global_expl_inline = 42; //ok
inline int static global_expl_inline_explicit_static = 42; //? external linkage by default but static explicit but still ok?
inline int extern global_expl_inline_explicit_extern = 42; //UB
}
namespace {
inline int extern global_expl_inline_explicit_extern_but_unnamed_ns = 42; //ok
}
struct bar{
static int const in_class_static = 42;//ok
static int in_class_but_out_of_source_def;
};
int bar::in_class_but_out_of_source_def = 42;//UB
#endif
嗯...既然你实际上让自己对你的问题感到困惑,我想我应该进一步研究它。首先,我们必须对变量的相关属性进行分类:生命周期、可见性、链接
这些受到关键词的影响:static
, inline
, constexpr
, const
, extern
您在问题中使用的。
在变量定义的命名空间范围内:
- static
:指定内部链接
- inline
:允许在不同的翻译单元中对同一变量进行多个相同的定义,并确保它们引用相同的对象(例如具有相同的地址)
- constexpr
: 暗示const
- const
:默认为外部链接
- extern
:指定外部链接
Thus,
- global_non_expl_inline
:默认为外部链接。没问题,除非另一个翻译单元定义了另一个具有外部链接的此类变量。
- global_non_expl_inline_static
: 内部链接。很好,只要您不在任何地方定义其他此类变量即可。
- global_expl_inline
:外部链接和inline
。没问题,除非另一个翻译单元声明了另一个这样的变量而没有inline
.
- global_expl_inline_explicit_static
: 好吧,一个static inline
变量是有意义的,如果您不希望它在链接时可用,但确实希望在所有翻译单元中使用相同的变量 - 例如对各种常量有用。
- global_expl_inline_explicit_extern
:外部链接和inline
。没问题,除非另一个翻译单元声明了另一个这样的变量而没有inline
.
- global_expl_inline_explicit_extern_but_unnamed_ns
:内部链接根据参考参数 https://en.cppreference.com/w/cpp/language/storage_duration.
在班级范围内:
- in_class_static
: 外部链接。很好,根据参考参数 https://en.cppreference.com/w/cpp/language/static,但如果使用 odr,则需要在命名空间范围内进行声明。
- in_class_but_out_of_source_def
: 外部链接。也还好。这实际上是标准方式。
总之,未定义的行为比您想象的要少得多 - 这很好。然而,有一些事情是有效的,但并没有真正意义,比如extern
在未命名的命名空间中。
关于您对此问题的评论:我无法重现该问题并且该问题评论部分的其他人也不能。您可以在评论部分找到该问题的其他合理性问题。请记住,stackoverflow 上的一些问题是由那些不完全知道遇到问题时采取哪些步骤的人提出的。我不会太关心这个特定问题;)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)