在MSVC上的数组初始化期间,析构函数无需复制或移动构造函数

wal*_*lly 2 c++ visual-studio visual-c++

我在调试和发布版本的MSVC版本19.10.25019.0和19.11.25547.0上尝试了这个并得到相同的结果.


打印以下程序0 1 2 3 4 5.我也预料到了

  • 没有输出,或
  • 移动或复制构造函数调用与析构函数调用的组合.

相反,似乎为7个元素中的6个调用了析构函数,并且没有进行复制或移动构造函数调用.

#include <iostream>

struct MyChar {
    MyChar(char c) : c{c}{}
    MyChar() = default;

    MyChar(const MyChar&) { std::cout << "copy"; };
    MyChar& operator=(const MyChar&) { std::cout << "assign"; return *this; };
    MyChar(MyChar&&) { std::cout << "move"; };
    MyChar& operator=(const MyChar&&) { std::cout << "move assign"; return *this; };

    ~MyChar() { std::cout << cnt++ << '\t'; }

    char c{'H'};
    static int cnt;
};

int MyChar::cnt{};

int main()
{
    auto arr1 = new MyChar[7]{'D'};
}
Run Code Online (Sandbox Code Playgroud)

为什么析构函数被调用6次而没有删除(或者没有编译器通过复制或移动进行初始化)?

120*_*arm 6

在VC编译器中使用它并检查生成的汇编代码时,这似乎是与MyChar() = default构造函数相关的编译器错误.用它取代它MyChar() { }可以消除意外的析构函数调用.

通过在析构函数中添加一些额外的代码,被销毁的对象是默认初始化的成员arr1.添加一个调用delete [] arr1,同时包括在析构函数中被销毁的对象的地址,显示第一个元素被销毁一次,而另外6个被销毁两次 - 一次arr1构建时,再次删除调用时.

这应该报告给微软.它发生在VC2015和VC2017中.