我有一个带数组的简单结构:
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
};
我面对这些功能的不同表现。有趣的是,性能差异取决于我如何声明结构的默认构造函数。我有三种方式:
testDefault()
我认为从编译器的角度来看它们都是一样的。从来没有我这么错。我确实使用结构testValue()
,A
和B
多次运行C
和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
并测量了性能。这就是我所拥有的:
{{1}}
请注意隐式和默认构造函数的性能明显更差。只有空构造函数才能正确显示两种不同初始化表单的相同性能。
我用VC ++,gcc和clang测试了这个。见online demo for gcc。时间很持久。
我认为是:
由于所有编译器都表现出相同的时序,似乎我错过了一些东西。有人可以解释一下这些时间吗?
(另请参阅关于同一主题的问题Why compilers put zeros into arrays while they do not have to?。我在那里提供了一些指向cppreference的链接。)
答案 0 :(得分:5)
让我们看一下 value-initialize 的定义:
对T类型的对象进行值初始化意味着:
- 如果T是一个(可能是cv限定的)类类型,没有默认构造函数(12.1)或者是用户提供或删除的默认构造函数,那么该对象是默认初始化的;
- 如果T是(可能是cv限定的)类类型而没有用户提供或删除的默认构造函数,则该对象为零初始化[...];
- 如果T是数组类型,则每个元素都是值初始化的;
- 否则,该对象为零初始化。
另外,让我们回顾这里使用的形容词:
= default
或= delete
= default;
或隐式生成查看你的课程:
A
有一个默认构造函数,它被隐式声明为默认值,而不是用户提供的。C
有一个默认构造函数,用户声明为默认构造函数,而不是用户提供的。因此,value-initialize定义中的第二个要点适用。该对象为零初始化,意味着arr
被清零。
B
有一个默认构造函数,由用户提供。因此,value-initialize的第一个要点适用于B
;值初始化与此处的默认初始化相同,arr
未归零。
您的时间安排似乎与预期相符:A
或C
的值初始化为arr
,而其他情况则为{<1}}。
答案 1 :(得分:2)
其中一个构造函数在值初始化时表现不同。在这个版本中,
B() {};
当B::arr
为B
时,数组B::arr
未进行值初始化。和其他人一样。这是否能解释性能差异是另一回事。
因此,A::arr
不会通过值初始化进行零初始化,而C::arr
和arr
会进行初始化。所有三种情况在默认初始化下都具有相同的行为,也就是说,<div id="popup">Hello World!</div>
获取默认初始化,即不执行初始化。