值初始化

Value initialization

本文关键字:初始化      更新时间:2023-10-16

$8.5/7声明

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

我无法理解这句话的最后一部分"如果T隐式声明的默认构造函数是非平凡的,则调用该构造函数。">

有人能举例说明吗?

class A
{
    int x;
};
class B : A {};
B b{};

我认为上面代码中的B有一个非平凡的构造函数。但是,我如何观察对B隐式声明构造函数的调用,并确保我的编译器正在调用它呢?

我认为上面代码中的B有一个非平凡的构造函数。

在您的示例中,构造函数是琐碎的。

看看C++11 12.1/5中的条件,两个类都没有用户声明的构造函数、虚拟函数、虚拟基类、带初始化器的成员或类类型的成员;CCD_ 3没有基类,而CCD_。

但是,我如何观察对B隐式声明的构造函数的调用,并确保我的编译器正在调用它呢?

使类具有隐式但非平凡的默认构造函数的一种方法是具有非平凡的成员或基类:

struct A {
    // A user-declared constructor is non-trivial
    A() {std::cout << "Construct An";}
};
struct B : A {};

现在,您可以(间接(观察B的隐式构造函数被调用,方法是观察它调用A的构造函数时的副作用。

N3797之后的说明:

如果函数是用户声明的而不是显式的,那么它就是用户提供的在其第一次声明时默认或删除。

因此,由于您没有为B声明默认构造函数,因此它不是用户提供的。以下内容适用:

如果默认构造函数不是用户提供的,并且:

--它的类没有虚拟函数(10.3(,也没有虚拟基类别(10.1(和

--其类的任何非静态数据成员都没有大括号或相等的初始值设定项,以及

--其类的所有直接基类都有琐碎的默认值构造函数和

--对于其类中属于类的所有非静态数据成员类型(或其数组(,每个此类都有一个琐碎的默认值构造函数。

因此,这确实是微不足道的,因为我们可以递归地将相同的过程应用于A

其他示例:

struct A { A() = default; }; // Trivial default constructor!
struct A { A() = delete; }; // Also trivial!
struct A { A(); }; // Can't be trivial!
struct B { virtual void f(); }
struct A : B {}; // Non-trivial default constructor.
struct B {};
struct A : virtual B {}; // Non-trivial default constructor.

想象一下你有一个

struct A {
  string a;
  int value;
};
int main() {
  A a = A();
  return a.value;
}

当我们返回该值时,a.value为零,因为对象初始化为零。但这还不够,因为a还包含一个具有构造函数的字符串成员。对于要调用的构造函数,标准安排调用A的构造函数,这将最终导致构造成员。