C++ 默认初始化结构和值初始化结构的性能不同

C++ 默认初始化结构和值初始化结构的性能不同,c++,arrays,initialization,C++,Arrays,Initialization,我有一个带有数组的简单结构: struct A { uint32_t arr[size]; }; 我有两个函数,它们使用默认初始化和值初始化创建它: template<class T> void testDefault() { T* pa = new T; // Default use(*pa); delete pa; } template<class T> void testValue() { T* pa = new T(); // Valu

我有一个带有数组的简单结构:

struct A
{
  uint32_t arr[size];
};
我有两个函数,它们使用默认初始化和值初始化创建它:

template<class T>
void testDefault()
{
  T* pa = new T;  // Default
  use(*pa);
  delete pa;
}

template<class T>
void testValue()
{
  T* pa = new T();  // Value
  use(*pa);
  delete pa;
}
从编译器的角度来看,我认为它们都是一样的。我从来没有这么错过。我使用structs
A
B
C
多次运行了
testDefault()
testValue()
,并测量了性能。以下是我所拥有的:

Default initialization (implict constructor) done in 880ms
Value initialization (implict constructor) done in 1145ms
Default initialization (empty constructor) done in 867ms
Value initialization (empty constructor) done in 865ms
Default initialization (defaulted constructor) done in 872ms
Value initialization (defaulted constructor) done in 1148ms
请注意,隐式构造函数和默认构造函数的性能明显较差。对于两种不同的初始化形式,只有空构造函数才能正确地显示相同的性能

我用VC++、gcc和clang测试了这个。看见时间安排是相当持久的

我的假设是:

  • UDT的默认初始化和值初始化是相同的
  • 所有已演示的定义默认构造函数的方法都在做相同的事情
  • 这些结构的默认构造函数应使数组的内容处于不确定状态
  • 因为所有的编译器都显示相同的计时,所以我似乎遗漏了一些东西。谁能给我解释一下这些时间安排吗


    (另请参见我关于同一主题的问题。我在这里提供了一些指向cppreference的链接。)

    其中一个构造函数在值初始化下的行为不同。在这个版本中

    B() {};
    
    当调用
    B
    时,数组
    B::arr
    的值未初始化。和其他人一样,它是。这是否能解释性能差异是另一回事


    因此,
    B::arr
    不会通过值初始化得到零初始化,而
    A::arr
    C::arr
    会得到零初始化。这三种情况在默认初始化下都有相同的行为,也就是说,
    arr
    获得默认初始化,即不执行初始化。

    让我们看看值初始化的定义:

    初始化T类型对象的值意味着:

    • 如果T是一个(可能是cv限定的)类类型,没有默认构造函数(12.1),或者是用户提供或删除的默认构造函数,那么对象是默认初始化的
    • 如果T是一个(可能是cv限定的)类类型,没有用户提供或删除的默认构造函数,那么对象是零初始化[…]
    • 如果T是数组类型,则每个元素都初始化为值
    • 否则,对象初始化为零
    另外,让我们回顾一下这里为构造函数使用的形容词:

    • 用户声明-您声明了构造函数
    • 用户提供-您声明了构造函数,但未将其设置为
      =default
      =delete
    • 默认-可以在没有参数的情况下调用
    • 声明为默认-标记为
      =默认或隐式生成
    看看你的课程:

    • A
      有一个默认构造函数,隐式声明为默认构造函数,而不是用户提供的构造函数
    • C
      有一个默认构造函数,该构造函数由用户声明为默认构造函数,而不是由用户提供
    因此,值初始化定义中的第二个要点适用。对象已初始化为零,这意味着
    arr
    已调零

    • B
      具有用户提供的默认构造函数
    因此,值初始化的第一个项目符号适用于
    B
    ;值初始化与此处的默认初始化相同,
    arr
    未归零


    您的计时似乎与预期相符:
    A
    C
    的值初始化将
    arr
    归零,而其他情况则不然。

    为什么显式默认构造函数执行smth。和空的不一样?这里没有进行聚合初始化,不是吗?@BaummitAugen这是个好问题。可能是因为它试图尽可能地接近编译器。在
    default
    之前,无法恢复该行为wrt。默认值和值初始化。注意:提及聚合是一种误导;这只有在使用列表初始化时才起作用。此外,我使用[,,]来删除具有非平凡构造函数的类类型成员的类的行为描述,以使其保持简单的回答!我想知道为什么这里会提到没有默认构造函数和删除默认构造函数的类型。有可能初始化这样的类吗?@Mikhail我认为它只引用聚合(聚合初始化绕过任何构造函数),所以
    AGG AGG={}将值初始化,这解释了已删除的默认构造函数。但是类没有默认构造函数的唯一原因是它有其他用户定义的构造函数。但是,如果类具有用户提供的构造函数,则它不再是聚合。所以您认为这一行是指具有非用户提供的用户定义的非默认构造函数的类?
    
    B() {};