gpt4 book ai didi

c++ - 关于静态 const 数据成员的声明和定义的困惑

转载 作者:行者123 更新时间:2023-12-01 08:52:48 24 4
gpt4 key购买 nike

Scott Meyers 在 Effective Modern C++, Item 30 page 210 中写道,有

no need to define integral static const data members in classes; declarations alone suffice,


那么示例代码是
class Widget {
public:
static const std::size_t MinVals = 28; // MinVals' declaration;
...
};
... // no defn. for MinVals
std::vector<int> widgetData;
widgetData.reserve(Widget::MinVals); // use of MinVals
我确信 static const std::size_t MinVals = 28;是声明 还有一个定义,因为它给 MinVals 赋值,但评论似乎声称这只是一个声明;第二条评论实际上声称没有定义。代码后面的文字,确实是

MinVals lacks a definition.


这证实了 static const std::size_t MinVals = 28;不是一个定义,所以我有点困惑。
cppreference对我没有多大帮助(我的粗体斜体):

If a static data member of integral or enumeration type is declared const (and not volatile), it can be initialized with an initializer in which every expression is a constant expression, right inside the class definition:

struct X
{
const static int n = 1;
const static int m{2}; // since C++11
const static int k;
};
const int X::k = 3;

但是类中的前两行对我来说是定义。
以下关于 cppreference 的示例也是如此:
struct X {
static const int n = 1;
static constexpr int m = 4;
};
const int *p = &X::n, *q = &X::m; // X::n and X::m are odr-used
const int X::n; // … so a definition is necessary
constexpr int X::m; // … (except for X::m in C++17)

我会说 static const int n = 1;是一个定义,但它不是基于倒数第二个评论。

最佳答案

no need to define integral static const data members in classes; declarations alone suffice,



仅当该对象不是 ODR-used 时,单独声明就足够了。 ,也就是说,如果数据成员未在需要其地址存在的上下文中使用(例如绑定(bind)到引用或应用运算符 & )。初始化器的存在不等于定义。

在书中的示例中,很明显 MinVals不是 ODR 使用的,即编译器可以直接使用它的值,而不必在内存中创建对象,因此语句:
widgetData.reserve(Widget::MinVals);

变成:
widgetData.reserve(28);

但是,如果在任何其他地方, MinVals被 ODR 使用,这会使程序格式错误。

cppreference 中的所有其他示例都清楚地表明了何时使用 ODR 并需要定义,何时不需要:
struct X
{
const static int n = 1;
const static int m{2}; // since C++11
const static int k;
};
const int X::k = 3;
nm是带有初始化器的声明。尝试获取 n 的地址或 m应该失败。
struct X {
static const int n = 1;
static constexpr int m = 4;
};
const int *p = &X::n, *q = &X::m;
const int X::n;
constexpr int X::m;

表达式 &X::n&X::m算作 n 的 ODR 使用和 m ,分别(即请求地址)。对于 constexpr静态数据成员,在 C++17 之前需要定义。来自 C++17, static constexpr数据成员隐含 inline ,这意味着不需要类外定义,因为它们本身就是定义。

关于c++ - 关于静态 const 数据成员的声明和定义的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61856487/

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