gpt4 book ai didi

c++ - C++ 中如何使用内联说明符来保留一个定义规则?

转载 作者:行者123 更新时间:2023-12-04 16:52:50 24 4
gpt4 key购买 nike

我一直试图弄清楚 inline说明符保留 ODR。到目前为止,我写的所有东西似乎都没有必要,因为包含保护确保定义只包含一次。
假设我在名为 constants.h 的文件中有以下定义

#ifndef CONSTANTS_H
#define CONSTANTS_H

namespace constants {
inline const double pi { 3.14159255358979323846 };
inline const double e { 2.71828182845904523536 };
}

#endif
以我对 inline的理解关于 ODR, inline编写说明符以确保这些常量的定义仅在多个翻译单元中初始化一次。因此,如果我将此文件包含在 a.cpp 中和 b.cpp一切都应该很好。
现在,让我们删除 inline关键词。
#ifndef CONSTANTS_H
#define CONSTANTS_H

namespace constants {
const double pi { 3.14159255358979323846 };
const double e { 2.71828182845904523536 };
}

#endif
现在,如果我将其包含在 a.cpp 中和 b.cpp没有问题。我想这是因为包含 guard 确保同一事物的多个定义不会出现两次。
接下来,让我们移除包含守卫
namespace constants {
const double pi { 3.14159255358979323846 };
const double e { 2.71828182845904523536 };
}
还是没问题。也许是因为 const默认情况下,限定的变量定义具有内部链接。结果,包括 constants.ha.cppb.cpp默认情况下,将这些定义中的每一个都设置为它们各自的翻译单元的内部。
很难打破跨多个翻译单元的 ODR。现在让我们删除 const。
namespace constants {
double pi { 3.14159255358979323846 };
double e { 2.71828182845904523536 };
}
现在! ODR 跨越多个翻译单元。让我们尝试用 inline 解决这个问题这样编译器就知道只定义这些变量一次。
namespace constants {
inline double pi { 3.14159255358979323846 };
inline double e { 2.71828182845904523536 };
}
好的,没有更多错误,这个文件可以再次包含在多个翻译单元中。那么为什么将头文件中的常量声明为 inline 被认为是“最佳实践”? ?打破ODR和 inline好像要下很多功夫在包含守卫存在的情况下是多余的。

最佳答案

未使用说明符 extern 声明的常量具有内部链接。
所以所有包含这些声明的编译单元

namespace constants {
const double pi { 3.14159255358979323846 };
const double e { 2.71828182845904523536 };
}
有自己的常数 pi 和 e。
来自 C++ 14 标准(3.5 程序和链接)

3 A name having namespace scope (3.3.6) has internal linkage if it isthe name of

(3.2) — a variable of non-volatile const-qualified type that isneither explicitly declared extern nor previously declared to haveexternal linkage; or


与上述声明相反,这些声明
namespace constants {
double pi { 3.14159255358979323846 };
double e { 2.71828182845904523536 };
}
有外部联动。因此,如果这些声明(也是定义)包含在多个编译单元中,则编译器会发出错误消息,因为一个定义规则被破坏。
例如,如果您在未命名的命名空间中声明它们,则可以使上述变量具有内部链接
namespace constants {
namespace {
double pi { 3.14159255358979323846 };
double e { 2.71828182845904523536 };
}
}
至于这些声明
namespace constants {
inline double pi { 3.14159255358979323846 };
inline double e { 2.71828182845904523536 };
}
然后可以在多个编译单元中定义具有外部链接的内联变量。此外,应在 ODR 使用的每个编译单元中定义一个内联变量。

关于c++ - C++ 中如何使用内联说明符来保留一个定义规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69966903/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com