gpt4 book ai didi

c++11 - 类成员初始化的首选方式?

转载 作者:行者123 更新时间:2023-12-04 20:35:44 25 4
gpt4 key购买 nike

class A { public: int x[100]; };

申报 A a不会初始化对象(可以通过字段 x 中的垃圾值看到)。
以下将触发初始化: A a{}auto a = A()auto a = A{} .

应该优先选择三者中的任何一个吗?

接下来,让我们让它成为另一个类的成员:
class B { public: A a; };
B的默认构造函数似乎负责 a 的初始化.
但是,如果使用自定义构造函数,我必须照顾它。
以下两个选项有效:
class B { public: A a;  B() : a() { } };

或者:
class B { public: A a{};  B() { } };

应该首选两者中的任何一个吗?

最佳答案

初始化

class A { public: int x[100]; };

Declaring A a will not initialize the object (to be seen by garbage values in the field x).



正确 A a定义时没有初始化器,并且不满足 default initialization 的任何要求.

1) The following will trigger initialization:

A a{};


是的;
  • a{}执行 list initialization其中
  • 变成 value initialization如果 {}是空的,或者可能是 aggregate initialization如果 A是一个集合。
  • 即使删除默认构造函数也能工作。例如A() = delete; (如果“A”仍被视为聚合)
  • 将警告缩小转换。


  • 2) The following will trigger initialization:

    auto a = A();


    是的;
  • 这是 copy initialization其中一个纯右值临时是用 direct initialization 构造的()哪一个
  • 用途 value initialization如果()是空的。
  • 没希望了 aggregate initialization .
  • 然后将纯右值临时用于 direct-initialize物体。
  • Copy elision可能并且通常被用来优化复制和构造 A到位。
  • 允许跳过复制/移动构造函数的副作用。
  • 移动构造函数不能被删除。例如 A(A&&) = delete;
  • 如果删除了复制构造函数,则必须存在移动构造函数。例如A(const A&) = delete; A(A&&) = default;
  • 不会警告缩小转换。


  • 3) The following will trigger initialization:

    auto a = A{}


    是的;
  • 这是 copy initialization其中一个纯右值临时是用 list initialization 构造的{}哪一个
  • 用途 value initialization如果 {}为空,或者如果 A 可能是聚合初始化是一个集合。
  • 然后将纯右值临时用于 direct-initialize物体。
  • Copy elision可能并且通常被用来优化复制和构造 A到位。
  • 允许跳过复制/移动构造函数的副作用。
  • 移动构造函数不能被删除。例如 A(A&&) = delete;
  • 如果删除了复制构造函数,则必须存在移动构造函数。例如A(const A&) = delete; A(A&&) = default;
  • 将警告缩小转换。
  • 即使删除默认构造函数也能工作。例如A() = delete; (如果“A”仍被视为聚合)

  • Should any particular one of the three be preferred?



    显然你应该更喜欢 A a{} .

    成员初始化

    Next, let us make it a member of another class:

    class B { public: A a; };

    The default constructor of B appears to take care of initialization of a.



    不,这是不正确的。
  • 'B' 的隐式定义的默认构造函数将调用 A 的默认构造函数,但不会初始化成员。不会触发直接或列表初始化。声明 B b;对于这个例子将调用默认构造函数,但留下不确定的值 A的数组。

  • 1) However, if using a custom constructor, I have to take care of it. The following two options work:

    class B { public: A a;  B() : a() { } };


    这会起作用;
  • : a()constructor initializera()是成员初始值设定项,作为 member initializer list 的一部分.
  • 用途 direct initialization ()或者,如果 ()为空,value initialization .
  • 没有希望使用聚合初始化。
  • 不会警告缩小转换。

  • 2) or:

    class B { public: A a{};  B() { } };


    这会起作用;
  • a现在有一个 non-static data member initializer ,如果您使用聚合初始化并且编译器是 not fully C++14 compliant,则可能需要构造函数来初始化它。 .
  • 成员初始化器使用 list initialization {}其中
  • 可能会变成 value initialization如果 {}为空或 aggregate initialization如果 A是一个集合。
  • a是唯一的成员,则不必定义默认构造函数,默认构造函数将被隐式定义。

  • 显然,您应该更喜欢第二种选择。

    就个人而言,我更喜欢在任何地方使用大括号,使用 some exceptionsauto以及构造函数可能将其误认为 std::initializer_list 的情况:
    class B { public: A a{}; };

    一个 std::vector对于 std::vector<int> v1(5,10),构造函数的行为会有所不同和 std::vector<int> v1{5,10} .与 (5,10)你会得到 5 个元素,每个元素的值为 10,但是 {5,10}你会得到两个分别包含 5 和 10 的元素,因为 std::initializer_list如果您使用大括号,则强烈首选。这在 Scott Meyers 的 Effective Modern C++ 第 7 条中有很好的解释。

    专供 member initializer lists ,可以考虑两种格式:
  • Direct initialization a()变成 value initialization如果()是空的。
  • List initialization a{}也变成 value initialization如果 {}是空的。

  • 在成员初始值设定项列表中,幸运的是,没有最烦人的解析的风险。在初始化列表之外,作为自己的声明, A a()会声明一个函数 vs. A a{}这会很清楚。另外, list initialization具有防止缩小转换的好处。

    所以,总而言之,这个问题的答案是,这取决于您想确定什么,这将决定您选择的表格。对于空的初始值设定项,规则更宽容。

    关于c++11 - 类成员初始化的首选方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36270612/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com