为什么隐式生成的构造函数(等)比用户定义的(普通的)更有效?

时间:2010-11-25 10:08:35

标签: c++ performance c++11 constructor

我今天早上从D. Kalev那里读到了article关于新的c ++ 11功能“默认和删除的功能”,并且无法理解有关性能的部分,即:

  

特殊成员函数的手动定义(即使它是微不足道的)通常比隐式定义的函数效率低。

通过谷歌搜索找到答案,我找到了同一作者的另一个article

  

合成的构造函数和复制构造函数使实现能够创建比用户编写的代码更高效的代码,因为它可以应用并非总是可能的优化。

没有解释,但我及时阅读类似的说法。

但是如何写作:

class C { C() = default; };

更有效率
class C { C(){} };

?我虽然编译器足够聪明,可以检测到这种情况并对其进行优化。换句话说,编译器在看到=default而不是{}(void body function)时如何更容易进行优化?

编辑:编辑问题是为了添加“c ++ 11”标签,但这个问题仍然存在于c ++ 03上下文中:只需将class C {C()=default;};替换为class C {};,所以不是真正的c ++ 11具体问题。

4 个答案:

答案 0 :(得分:7)

你问,怎么回事?

class C { C() = default; };

更有效率
class C { C(){} };

嗯,两个构造函数都不做任何事情,所以谈论这个例子的效率是没有意义的。

但更一般地说,例如,复制构造函数可以想象,一次复制一个POD项目将不会被简单的优化器识别为可优化,而使用自动生成它可能只会执行memcpy。谁知道。这是一个实施质量问题,我也很容易想象相反的

所以,衡量一下,如果重要的话。

干杯&第h。,

答案 1 :(得分:4)

无论如何谈论“特殊成员函数的手动定义(即使它是微不足道的)”都没有意义,因为根据定义,用户提供的特殊成员函数是非平凡的。这种非平凡性在使用类型特征和POD-ness时起作用,并且许多优化只能用于普通或POD类型。

更好地重述相同的引用:

默认的特殊成员函数使能够检测到对这些函数的调用可能完全被忽略。

来自第12.1节[class.ctor]

  

如果默认构造函数是琐事   既不是用户提供也不是删除   如果:

     
      
  • 它的班级没有虚拟   函数(10.3)并没有虚拟基础   类(10.1)和
  •   
  • 没有非静态   其类的数据成员有一个   支持或等于初始化器,和
  •   
  • 所有   同类的直接基类   有简单的默认构造函数,
  •   
  • 表示所有非静态数据成员   其类类型的类   (或其阵列),每个这样的类   有一个普通的默认构造函数。
  •   
     

否则,默认构造函数是   非平凡

从第12.8节[class.copy]

开始
  

X类的复制/移动构造函数是   琐碎如果它既不是用户提供的   也没删除,如果

     
      
  • X级没有   虚函数(10.3)和没有   虚基类(10.1)和
  •   
  • 选择复制/移动的构造函数   每个直接基类子对象都是   琐碎的,
  •   
  • 为每个非静态   类的X数据成员   (或其数组),构造函数   选择复制/移动该成员是   琐碎;
  •   
     

否则复制/移动   构造函数是非平凡的

从第9节[class]

开始
  

平易可复制的类是一个类   那个:

     
      
  • 没有非平凡的副本   构造函数(12.8),
  •   
  • 没有   非平凡的移动构造函数(12.8),
  •   
  • 没有非平凡的副本分配   运营商(13.5.3,12.8),
  •   
  • 没有   非平凡的移动分配算子   (13.5.3,12.8)和
  •   
  • 有一个小事   析构函数(12.4)。
  •   
     

普通类是一个有类的   普通的默认构造函数(12.1)和   很容易复制。 [注意:在   特别是,一个简单的可复制或   琐碎的班级没有虚拟   函数或虚拟基类。 -   结束说明]

答案 2 :(得分:2)

以“一粒盐”来表达业绩声明。

我听说一位高评级的麻省理工学院教授为他最喜欢的事情提出这样的主张,而且没有人问他“为什么”的唯一原因是因为他是麻省理工学院的高级教授。

这样的构造函数和析构函数可能具有其他优点,但是除非在非常人为的情况下,关于性能的声明(在大O之外)很少有意义。

答案 3 :(得分:0)

说实话,我也看不到它。

除此之外,我可以看到为什么要使用

class C { C() = default; };

在我看来与

相同
class C { };

或者,如果提供了其他构造函数,则为:

class C { 
    C() {}
    // other constructors.
};

我没有看到作者在这里写的真正的问题