【问题标题】:What is a non-trivial constructor in C++?什么是 C++ 中的非平凡构造函数?
【发布时间】:2010-10-10 06:06:31
【问题描述】:

我在读这个http://en.wikipedia.org/wiki/C%2B%2B0x#Modification_to_the_definition_of_plain_old_data

它提到了平凡的默认构造函数,平凡的复制构造函数,复制赋值运算符,平凡的析构函数。什么是微不足道的,什么不是微不足道的?

【问题讨论】:

    标签: c++ constructor


    【解决方案1】:

    简单来说,“平凡的”特殊成员函数的字面意思是一个以非常直接的方式完成其工作的成员函数。 “直截了当的方式”对于不同类型的特殊成员函数意味着不同的东西。

    对于默认构造函数和析构函数来说,“微不足道”的字面意思是“什么都不做”。对于复制构造函数和复制赋值运算符,“平凡”的字面意思是“等同于简单的原始内存复制”(如使用 memcpy 复制)。

    如果你自己定义了一个构造函数,它被认为是非平凡的,即使它不做任何事情,所以一个平凡的构造函数必须由编译器隐式定义。

    为了使特殊的成员函数满足上述要求,类必须具有非常简单的结构,在创建或销毁对象时必须不要求任何隐藏的初始化,或者在对象被创建时不要求任何隐藏的附加内部操作被复制。

    例如,如果类具有虚函数,则在创建该类的对象时将需要一些额外的隐藏初始化(初始化虚方法表等),因此该类的构造函数不会被认为是微不足道的。

    再举个例子,如果一个类有虚拟基类,那么这个类的每个对象都可能包含指向同一个对象其他部分的隐藏指针。这种自引用对象不能通过简单的原始内存复制例程(如memcpy)复制。需要进行额外的操作才能正确重新初始化副本中的隐藏指针。由于这个原因,这个类的复制构造函数和复制赋值运算符不会被认为是微不足道的。

    出于显而易见的原因,这个要求是递归的:类的所有子对象(基类和非静态成员)也必须有普通的构造函数。

    【讨论】:

    • 什么都不做... 那么什么是复制赋值运算符呢? ;)
    • @acidzombie24:我做了一些更正以涵盖复制成员函数。你的第二条评论我不清楚。任何用户定义的构造函数都是不平凡的,所以一旦你定义了它,这个类就不再是一个 POD。
    • 优秀的帖子。我想知道我是否有像struct Rect1 { int l, r, w, h}; struct Rect2 { int l, t, r, b' Rect2(){} Rect2(Rect1 r) {...} }; 这样的结构会被认为是微不足道的。但我想不是,因为我不允许定义任何 ctors。我会认为这是允许的,因为有一个微不足道的默认 ctor,这不是赋值或复制运算符
    • @acidzombie24:当你声明 any 构造函数时,你会抑制默认构造函数的隐式声明。所以,你的类将有 no 默认构造函数。在 C++0x 之前的语言中就是这样。在 C++0x AFAIK 中,您仍然可以强制编译器生成默认构造函数,这需要使用关键字 default 进行显式声明,如链接所示。
    • @AndreyT:非常出色。
    【解决方案2】:

    如果满足以下所有条件,则 A 类的构造函数为 trivial

    • 隐式定义(编译器合成)
    • A 没有虚函数,也没有虚基类
    • A 的所有直接基类都有普通的构造函数
    • A 的所有非静态数据成员的类都有普通的构造函数

    【讨论】:

    • 对不起,如果这听起来很愚蠢,但它也适用于析构函数吗?
    【解决方案3】:

    已经有正确的答案,但这里是来自标准的引用(我在看到这篇文章时正在寻找):

    (§12.1/5) 如果默认构造函数不是用户提供的并且如果:
    — 它的类没有虚函数 (10.3) 和虚基类 (10.1),并且
    — 其类的非静态数据成员没有大括号或等号初始化器,并且
    — 其类的所有直接基类都有微不足道的默认构造函数,并且
    — 对于其类的所有属于类类型(或其数组)的非静态数据成员,每个此类都有一个简单的默认构造函数。

    这是来自 C++11。 C++03 缺少第二项并使用短语隐式声明而不是非用户提供。在其他方面是相同的。

    请注意,本规范仅涵盖琐碎的默认构造函数。词属性 trivial 也可以在不同的上下文中使用,例如复制构造函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-27
      • 2018-10-28
      • 2015-08-26
      • 2015-08-10
      相关资源
      最近更新 更多