[英]Different performance for default initialized and value initialized struct
I have a simple struct with an array: 我有一个带数组的简单结构:
struct A
{
uint32_t arr[size];
};
I have two functions, which create it using default initialization and value initialization: 我有两个函数,使用默认初始化和值初始化创建它:
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;
}
I'm facing different performance for those functions. 我面临着这些功能的不同表现。 The funny thing is that performance differences vary depending on how I declare default constructor of the struct.
有趣的是,性能差异取决于我如何声明结构的默认构造函数。 I have three ways:
我有三种方式:
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
};
I thought they are all the same from compiler's point of view. 从编译器的角度来看,我认为它们都是一样的。 Never have been I so wrong.
从来没有我这么错。 I did run both
testDefault()
and testValue()
several times with structs A
, B
and C
and measured performance. 我确实用结构
A
, B
和C
运行了testDefault()
和testValue()
几次并测量了性能。 Here is what I have: 这是我有的:
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
Note how performance is clearly worse for both implicit and defaulted constructors. 注意隐式和默认构造函数的性能如何明显更差。 Only empty constructor correctly shows the same performance for both different initialization forms.
只有空构造函数才能正确显示两种不同初始化表单的相同性能。
I tested this with VC++, gcc and clang. 我用VC ++,gcc和clang测试了这个。 See online demo for gcc .
请参阅gcc的在线演示 。 Timings are quite persistent.
时间非常持久。
What I assume is: 我假设是:
Since all the compilers exhibit the same timings, it seems like I'm missing something. 由于所有编译器都表现出相同的时序,似乎我错过了一些东西。 Can anyone please explain me these timings?
有人可以解释一下这些时间吗?
(See also my question Why compilers put zeros into arrays while they do not have to? on the same topic. I give some links to cppreference there.) (另请参阅我的问题为什么编译器将零放入数组而不必使用?在同一主题上。我在那里提供了一些指向cppreference的链接。)
Let's look at the definition of value-initialize : 让我们看一下value-initialize的定义:
To value-initialize an object of type T means:
对值类型T的对象进行值初始化意味着:
- if T is a (possibly cv-qualified) class type with either no default constructor (12.1) or a default constructor that is user-provided or deleted, then the object is default-initialized;
如果T是一个(可能是cv限定的)类类型,没有默认构造函数(12.1)或者是用户提供或删除的默认构造函数,那么该对象是默认初始化的;
- if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized [...];
如果T是一个(可能是cv限定的)类类型而没有用户提供或删除的默认构造函数,那么该对象是零初始化的[...];
- if T is an array type, then each element is value-initialized;
如果T是数组类型,那么每个元素都是值初始化的;
- otherwise, the object is zero-initialized.
否则,该对象被零初始化。
Also let's review the adjectives in use here for constructors: 另外,让我们回顾一下构造函数在这里使用的形容词:
= default
or = delete
= default
或= delete
= default;
= default;
or implicitly generated as such Looking at your classes: 看你的课程:
A
has a default constructor which is implicitly declared as defaulted, and not user-provided. A
有一个默认构造函数,它被隐式声明为默认值,而不是用户提供的。 C
has a default constructor which is user-declared as defaulted, and not user-provided. C
有一个默认构造函数,用户声明为默认构造函数,而不是用户提供的构造函数。 So the second bullet point in the definition of value-initialize applies. 因此,value-initialize定义中的第二个要点适用。 The object is zero-initialized, meaning the
arr
is zeroed out. 该对象是零初始化的,这意味着
arr
被清零。
B
has a default constructor which is user-provided. B
有一个用户提供的默认构造函数。 So the first bullet point of value-initialize applies to B
; 所以value-initialize的第一个要点适用于
B
; value-initialization is the same as default-initialization here, and arr
is not zeroed out. value-initialization与此处的default-initialization相同,并且
arr
不会被清零。
Your timings correctly seem to correspond to what is expected: value-initialization of A
or C
zeroes out arr
and the other cases don't. 你的时间正确地看起来与预期相符:
A
或C
值初始化将arr
排除在外,而其他情况则不然。
One of the constructors behaves differently under value initialization. 其中一个构造函数在值初始化下表现不同。 In this version,
在这个版本中,
B() {};
the array B::arr
is not value-initialized when the B
is. 当
B
是时,数组B::arr
没有进行值初始化。 With the others, it is. 和其他人一样。 Whether this explains the performance difference is another matter.
这是否解释了性能差异是另一回事。
So, B::arr
doesn't get zero-initialized with value initialization, whereas A::arr
and C::arr
do. 因此,
B::arr
不会通过值初始化进行零初始化,而A::arr
和C::arr
可以。 All three cases have the same behaviour under default initialization, that is to say, arr
gets default-initialized , ie no initialization is performed. 所有三种情况在默认初始化下都具有相同的行为,也就是说,
arr
得到默认初始化 ,即不执行初始化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.