gpt4 book ai didi

c++ - C++中关于常量初始化和零初始化的顺序的矛盾定义

转载 作者:行者123 更新时间:2023-12-04 12:17:51 29 4
gpt4 key购买 nike

我一直试图了解静态变量是如何初始化的。并在cppref处注意到常量初始化和零初始化的顺序矛盾。和 enseignement .
cppref它说:

Constant initialization is performed instead of zero initialization of the static and thread-local (since C++11) objects and before all other initialization.


而在 enseignement它说:

Constant initialization is performed after zero initialization of the static and thread-local objects and before all other initialization.


因此,您可以看到 cppref 使用“代替”,而第二个站点使用“之后”。 两者哪个是正确的? 即,是否进行零初始化 总是 首先发生,然后如果可能的话,如第二个站点所暗示的那样进行常量初始化,或者反过来。
那里给出的例子如下:
#include <iostream>
#include <array>

struct S {
static const int c;
};
const int d = 10 * S::c; // not a constant expression: S::c has no preceding
// initializer, this initialization happens after const
const int S::c = 5; // constant initialization, guaranteed to happen first
int main()
{
std::cout << "d = " << d << '\n';
std::array<int, S::c> a1; // OK: S::c is a constant expression
// std::array<int, d> a2; // error: d is not a constant expression
}
这是我目前对初始化过程的理解:
  • 静态初始化首先发生。这包括
  • 如果可能,持续初始化
  • 仅当未完成常量初始化时才进行零初始化
  • 动态初始化

  • 现在根据上述(我的理解)这是上面代码的工作原理:
    第 1 步。
    当控制流到达 const int d的定义时它看到初始化程序有一个尚未初始化的变量(即 S::c )。所以声明 const int d = 10 * S::c;是动态时间(运行时)初始化。这意味着它只能在静态初始化之后发生。当然还有 d不是常量表达式。
    第 2 步。
    控制流到达变量 const int S::c;的定义.然而,在这种情况下,初始化器是一个常量表达式,因此可能会发生常量初始化。并且不需要零初始化。
    第 3 步。
    但请注意,我们(编译器)还没有初始化变量 d因为它离开了初始化,因为它必须动态完成。所以现在这将发生, d将获得值 50。但请注意 d仍然不是常量表达式,因此我们不能在需要常量表达式的地方使用它。
    我对概念的分析/理解是否正确,代码的行为是否如所述?
    笔记:
    常量初始化和零初始化的顺序在 cppref-init处也是不同的和 enseignement-init .

    最佳答案

    如有疑问,请转向标准。由于这个问题被标记为 C++11,我们将引用 N3337 .
    [basic.start.init]/2 :

    Variables with static storage duration ([basic.stc.static]) or threadstorage duration ([basic.stc.thread]) shall be zero-initialized([dcl.init]) before any other initialization takes place.

    Constant initialization is performed: [...]

    Together, zero-initialization and constant initialization are calledstatic initialization; all other initialization is dynamicinitialization. Static initialization shall be performed before anydynamic initialization takes place.


    因此,对于 C++11 标准,enseignement 的描述是准确的。

    Constant initialization is performed after zero initialization of the static and thread-local objects and before all other initialization.


    但是,根据 CWG 2026,这被标记为缺陷。 :

    CWG agreed that constant initialization should be considered as happening instead of zero initialization in these cases, making the declarations ill-formed.


    从 C++17 ( N4659 ) 开始,这已更改,此后由 [basic.start.static]/2 管理:

    [...] Constant initialization is performed if a variable or temporary object with static or thread storage duration is initialized by a constant initializer for the entity. If constant initialization is not performed, a variable with static storage duration or thread storage duration is zero-initialized. Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization.


    但由于这不仅仅是新标准功能更新,而是一个缺陷,它向后移植到旧标准,最终 cppreference 的描述对于 C++11 也是准确的(实际上一直回到 C++98),而enseignement 既没有考虑现代 C++ 标准,也没有考虑 DR CWG 2026。
    我自己从来没有访问过 enseignement 的页面,但是在快速浏览一下他们的引用页面后,它看起来像是一个非常旧版本的 cppreference 本身, 要么完全未归属 到 cppreference,或者 cppreference 实际上是作为与 enseignement 作者的合作开始的。
    缺少标准本身,我认为 cppreference 是事实上的引用,并且考虑到 enseignement 的旧复制面食,我建议永远不要再转向那些页面引用。事实上,我们可以访问 the actual up-to-date cppreference page on constant initialization ,滚动到最底部并阅读:

    Defect reports

    The following behavior-changing defect reports were appliedretroactively to previously published C++ standards.

    [...]

    • CWG 2026
      • Applied to: C++98
      • Behavior as published: zero-init was specified to always occur first, even before constant-init
      • Correct behavior: no zero-init if constant init applies

    关于c++ - C++中关于常量初始化和零初始化的顺序的矛盾定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69264430/

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