用于静态变量的Constexpr构造函数会导致动态初始化

时间:2019-04-04 18:24:44

标签: c++ visual-c++ constexpr static-variables static-initialization

我有以下程序:

$('#searchbox').keyup(function (){
    $('.col-lg-4').removeClass('d-none');
    var filter = $(this).val();
    if (filter && filter.length>0){
        $('.row').find('.col-lg-4 .card-body h5:not(:contains("'+filter+'"))').parentsUntil('.col-lg-4').parent().addClass('d-none');
    }
});

这里#include <iostream> void Init(); struct Foo { Foo() { int *p = new int; // just to make sure Foo's ctor is not a constant expression Init(); } } foo; struct Bar { constexpr Bar() : value(0) { } int value; } bar; void Init() { bar.value = 1; } int main() { std::cout << bar.value << std::endl; } 的构造函数不是常量表达式,因此我们将动态初始化foo。但是foo的构造函数似乎是一个常量表达式,因此我们将静态初始化bar。因此,必须在bar之前调用bar的ctor,我们将看到foo作为输出。我在GCC 8.3.0和Clang 8.0.0中观察到了这样的结果。但是对于Visual C ++,实际输出为1,在调试应用程序时,我看到先进行0的动态初始化,然后进行foo的动态初始化。

我观察到的行为(bar根据C ++ 17标准是否有效?

我正在使用x ++ Debug版本或Release版本的C ++编译器版本19.16.27027.1,其ctor标记为bar.value == 0

1 个答案:

答案 0 :(得分:5)

  

但是bar的构造函数似乎是一个常量表达式,因此我们将静态初始化bar

那是不正确的认识。

constexpr构造函数也可以用于构造非const对象。发生这种情况时,将使用动态初始化来初始化该对象。在您的情况下,bar是非const对象。因此,可以使用动态初始化将其初始化。

将代码更改为:

struct Bar {
    constexpr Bar()
        : value(0) { }
    int value;
};

constexpr Bar bar;

应将bar的初始化更改为静态初始化。

但是,如果将bar更改为const对象,则将无法使用

bar.value = 1; 
Init()

。我只想指出如何更改bar,以便可以在静态初始化期间将其初始化。