gpt4 book ai didi

c++ - constexpr 初始化是否应该在其他初始化之前发生

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:34:06 28 4
gpt4 key购买 nike

我有以下代码,它在 gcc 和 clang 上的表现符合预期。然而,MSVC 给了我意想不到的结果。

让我们先看看有问题的代码。

#include <iostream>

// -----------------------------------------------

class Test // Dummy for MCVE
{
public:
Test();
void Print();
private:
int arr[5];
};

Test tst;

// -----------------------------------------------

template<typename T>
struct range // some stuff not needed by example removed
{
constexpr range(T n) : b(0), e(n) {}
constexpr range(T b, T e) : b(b), e(e) {}
struct iterator
{
T operator*() { return i; }
iterator& operator++() { ++i; return *this; }
bool operator!=(iterator other) { return i != other.i ; }
T i;
};
iterator begin() const { return{ b }; }
iterator end() const { return{ e }; }
private:
T b,e;
};

constexpr range<int> coord(5);

// -----------------------------------------------

Test::Test()
{
for(auto i : coord)
arr[i]=i;
}

void Test::Print()
{
for(auto i : coord)
std::cout << arr[i] << std::endl;
}

// -----------------------------------------------

int main()
{
tst.Print();
}


现在,在 clang 和 gcc 上打印 '0 1 2 3 4'
但是,在 MSVC 上,这将打印 '0 0 0 0 0'
原因是当全局变量 tst 上的构造函数运行时,'coord' 尚未初始化(至 0,5),但它也不是随机的,而是 (0,0)。
对我来说,constexpr 初始化发生在常规初始化之前是有意义的。 MSVC 是否符合此行为?

也许我应该注意到我使用的是 MSVC 版本 14.0.22823.1,并且可以通过更改顺序来获得预期的结果声明

最佳答案

对于静态存储持续时间对象,初始化必须按以下顺序进行:

  1. 零初始化。
  2. 常量初始化(即 constexpr)。
  3. 动态初始化。

相关标准,

C++14 §3.6.2/2:

Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place. […] Constant initialization is performed: […] if an object with static or thread storage duration is initialized by a constructor call, and if the initialization full-expression is a constant initializer for the object; […] Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place.

同一段定义(打断了文字的流向,所以我在上面去掉了)

A constant initializer for an object o is an expression that is a constant expression, except that it may also invoke constexpr constructors for o and its subobjects even if those objects are of non-literal class types.


在我用 Visual C++ 2015 验证的报告示例中,静态存储持续时间对象 tst 的动态初始化发生在静态存储持续时间对象 的常量初始化之前坐标,这是一个编译器错误。

关于c++ - constexpr 初始化是否应该在其他初始化之前发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31468247/

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