“令人惊讶”根据定义顺序进行常量初始化 [英] "surprising" constant initialization because of definition order

查看:80
本文介绍了“令人惊讶”根据定义顺序进行常量初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读关于constexpr的幻灯片时,引言是关于使用const进行动态初始化 。例子是

When reading the slides about constexpr the introduction is about "surprisingly dynamic initialization with consts". The example is

struct S {
    static const int c;
};
const int d = 10 * S::c;
const int S::c = 5;

A,音轨丢失了,音符也丢失了,所以我只能猜测是什么意思

Alas, the audio track is missing, so are the notes, so I can only guess what is meant here.

是否正确地动态初始化了 d ,因为 S :: c 是在之前 d 定义的?声明 S :: c 的em>在 d 之前还不够,编译器需要完整的定义,对吧?

Is it corrrect that d is "surprisingly" initialized dynamically, because S::c is defined before d? That the declaration of S::c is before d is probably not enough, the compiler needs the complete definition, right?

我怀疑这是在以下示例中的 d 静态初始化吗?

That said, I suspect, that in the following example d would be initialized statically?

struct S {
    static const int c;
};
const int S::c = 5;
const int d = 10 * S::c;  // now _after_ defn of S::c

的defn然后用C ++ 11制作蛋糕,什么是完全静态初始化的 constexpr S :: c d 还是两者都使用?

And to take the cake, in C++11, what would have to be constexpr for full static initialization? S::c, d or both?

推荐答案

在第一个示例中, d 未被常量表达式初始化,因为 S :: c 不是

In the first example, d is not initialized by a constant expression, because S::c is not


具有先前初始化的非易失性const对象,用常量表达式初始化的

a non-volatile const object with a preceding initialization, initialized with a constant expression

(请参见C ++ 11 [expr.const] p2,左值到右值转换的项目符号),因为 S :: c 不在 d 初始化之前。因此,静态初始化将用于 S :: c (因为它是通过常量表达式初始化的),而动态初始化可用于 d

(see C++11 [expr.const]p2, bullet on lvalue-to-rvalue conversions), because the initialization of S::c does not precede the initialization of d. Therefore static initialization will be used for S::c (because it is initialized by a constant expression), but dynamic initialization can be used for d.

由于静态初始化先于动态初始化,因此 d 将被初始化为 50 通过其动态初始值设定项。允许编译器将 d 的动态初始化转换为静态初始化,但是如果这样做,它必须产生 d 将会拥有。在这种情况下, d 都将初始化为 50 。有关更多信息,请参见C ++ 11 [basic.start.init] p2。

Since static initialization precedes dynamic initialization, d would be initialized to 50 by its dynamic initializer. The compiler is permitted to convert the dynamic initialization of d to static initialization, but if it does, it must produce the value that d would have had if every variable which could have used dynamic initialization had, in fact, used dynamic initialization. In this case, d is initialized to 50 either way. See C++11 [basic.start.init]p2 for more information on this.

无法添加 constexpr 到第一个示例,以确保 d 使用静态初始化;为此,您必须对初始化进行重新排序。但是,添加 constexpr 将为第一个示例生成诊断,这至少将使您确保不使用动态初始化 (您会得到静态初始化或编译错误)。

There is no way to add constexpr to the first example to guarantee that static initialization is used for d; in order to do that, you must reorder the initializations. However, adding constexpr will produce a diagnostic for the first example, which will at least allow you to ensure that dynamic initialization is not used (you get static initialization or a compilation error).

您可以更新第二种情况,以确保使用静态初始化的方式如下:

You can update the second case to ensure that static initialization is used as follows:

struct S {
    static const int c; // do not use constexpr here
};
constexpr int S::c = 5;
constexpr int d = 10 * S::c;

使用 constexpr 格式不正确在不是定义的变量声明中使用,或在不包含初始化程序的变量声明中使用它,因此 const ,而不是 constexpr 必须在 struct S 的定义内使用。该规则有一个例外,那就是在类中指定了初始化程序的情况下,定义文字,非整数类型的静态constexpr 数据成员时:

It is ill-formed to use constexpr on a variable declaration which is not a definition, or to use it on a variable declaration which does not contain an initializer, so const, not constexpr must be used within the definition of struct S. There is one exception to this rule, which is when defining a static constexpr data member of a literal, non-integral type, with the initializer specified within the class:

struct T { int n; };
struct U {
    static constexpr T t = { 4 };
};
constexpr T U::t;

在这种情况下,必须使用 constexpr 在类的定义中,为了允许提供初始化程序,必须在静态数据成员的定义中使用 constexpr 在常量表达式中。

In this case, constexpr must be used in the definition of the class, in order to permit an initializer to be provided, and constexpr must be used in the definition of the static data member, in order to allow its use within constant expressions.

这篇关于“令人惊讶”根据定义顺序进行常量初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆