繁体   English   中英

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

[英]Different performance for default initialized and value initialized struct

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

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;
}

我面临着这些功能的不同表现。 有趣的是,性能差异取决于我如何声明结构的默认构造函数。 我有三种方式:

struct A
{
  uint32_t arr[size];
  // Implicit constructor
};

struct B
{
  uint32_t arr[size];
  B() {};  // Empty constructor
};

struct C
{
  uint32_t arr[size];
  C() = default;  // Defaulted constructor
};

从编译器的角度来看,我认为它们都是一样的。 从来没有我这么错。 我确实用结构ABC运行了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测试了这个。 请参阅gcc的在线演示 时间非常持久。

我假设是:

  1. UDT的默认值和值初始化是相同的
  2. 所有已经证明的定义默认构造函数的方法都在做同样的事情
  3. 这些结构的默认构造函数应该使数组的内容处于不确定状态

由于所有编译器都表现出相同的时序,似乎我错过了一些东西。 有人可以解释一下这些时间吗?

(另请参阅我的问题为什么编译器将零放入数组而不必使用?在同一主题上。我在那里提供了一些指向cppreference的链接。)

让我们看一下value-initialize的定义:

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

  • 如果T是一个(可能是cv限定的)类类型,没有默认构造函数(12.1)或者是用户提供或删除的默认构造函数,那么该对象是默认初始化的;
  • 如果T是一个(可能是cv限定的)类类型而没有用户提供或删除的默认构造函数,那么该对象是零初始化的[...];
  • 如果T是数组类型,那么每个元素都是值初始化的;
  • 否则,该对象被零初始化。

另外,让我们回顾一下构造函数在这里使用的形容词:

  • user-declared - 您声明了构造函数
  • user-provided - 您声明了构造函数,但未将其设置为= default= delete
  • default - 可以不带参数调用
  • 声明为默认值 - 标记= default; 或隐含地生成

看你的课程:

  • A有一个默认构造函数,它被隐式声明为默认值,而不是用户提供的。
  • C有一个默认构造函数,用户声明为默认构造函数,而不是用户提供的构造函数。

因此,value-initialize定义中的第二个要点适用。 该对象是零初始化的,这意味着arr被清零。

  • B有一个用户提供的默认构造函数。

所以value-initialize的第一个要点适用于B ; value-initialization与此处的default-initialization相同,并且arr不会被清零。

你的时间正确地看起来与预期相符: AC值初始化将arr排除在外,而其他情况则不然。

其中一个构造函数在值初始化下表现不同。 在这个版本中,

B() {};

B是时,数组B::arr没有进行值初始化。 和其他人一样。 这是否解释了性能差异是另一回事。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM