【问题标题】:Can I choose between default-initalisation and value-initialisaion or all or part of an array?我可以在默认初始化和值初始化或全部或部分数组之间进行选择吗?
【发布时间】:2012-02-07 08:50:58
【问题描述】:

自 C++2003 以来,我们有值初始化和默认初始化。意思是:

struct Foo {
    int i;
    std :: string s;
};

Foo f1;          // f1.s is default-constructed, f1.i is uninitialised
Foo f2 = Foo (); // f1.s is default-constructed, f1.i is zero

对吗?

现在假设我有这门课

class Bar : public Foo {
    int n;
    Foo f [SIZE];
public:
    Bar ();
};

当我为Bar 编写构造函数时,我可能希望对父类或f[] 成员进行默认或值初始化。我认为初始化父母的选择很简单:

Bar :: Bar () : Foo (), n (-1) {} // Parent is value-initialised (Foo::i is zero)
Bar :: Bar () : n (-1)         {} // Parent is default-initialised (Foo::i is undefined)

但是f[] 成员呢?

  • 如何默认初始化所有成员?
  • 如何对所有成员进行值初始化?
  • 如果我使用 C++11 初始化列表,如果初始化列表的大小与 SIZE 不同,会发生什么情况?

【问题讨论】:

  • 请避免::周围有空格。
  • 为什么?我喜欢它,它更容易阅读。
  • @spraff 而你却使用 PascalCaseWhereWordsRunTogether?
  • 对于类型,是的,对于变量,不,我不给他们 LongNamesWhichSufferReadibilityProblems。但是,我们不要在 cmets 中进行风格大战。
  • 在第一个示例中,i 在默认初始化和从复制初始化中都将保持未初始化,不同之处在于在从复制初始化中 i将使用来自临时 Foo 的成员 i 的垃圾进行初始化。您使用它的方式从副本初始化通常较慢,因为它可能会导致临时对象创建(尽管大多数编译器不会创建额外的副本)。

标签: c++ value-initialization


【解决方案1】:

实际上,根据标准值初始化似乎是调用任何形式的用户定义的默认构造函数的过程或零初始化没有默认构造函数的对象(参见 8.5 [decl.init] 段落7:

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

——如果 T 是(可能是 cv 限定的)类类型(第 9 条),带有用户提供的构造函数(12.1),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数);

——如果 T 是一个(可能是 cv 限定的)非联合类类型,没有用户提供的构造函数,则该对象是零初始化的,如果 T 的隐式声明的默认构造函数是非平凡的,则该构造函数是调用。

——如果 T 是一个数组类型,那么每个元素都是值初始化的; — 否则,对象被零初始化。

从这个意义上说,您可以使用成员初始化器列表中的f() 从 C++1998 开始初始化您的数组成员。如果要使用特定值,则需要使用 C++2011 和初始化列表,例如f({ 1, 2, 3 })。如果参数的数量少于元素的数量,则剩余的元素将被初始化。实际上,它们是从一个空的初始化列表初始化的(8.5.1 [dcl.init.aggr] 第 7 段):

如果列表中的初始化子句少于聚合中的成员,则每个成员 未显式初始化应从空的初始化列表初始化。

...根据 8.5.4 [dcl.init.list] 第 3 段,第 7 条,从一个空的初始化列表进行初始化:

  • 否则,如果初始化列表中没有元素,则对象被值初始化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-29
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 2020-02-08
    • 2015-02-25
    • 2020-10-26
    相关资源
    最近更新 更多