Visual Studio 现代C++中的默认构造函数

bnl4lu3b  于 2023-10-23  发布在  其他
关注(0)|答案(2)|浏览(155)

当我运行这段代码时,VS编译器返回错误,并说t1.mem是未初始化的局部变量。

#include <string>
#include <iostream>
struct T1
{
  int mem;
};

struct T2
{
  int mem;
  T2() { } // "mem" is not in the initializer list
};

int main()
{

  T1 t1;            // class, calls implicit default ctor
  std::cout << t1.mem << std::endl;
  const T2 t2;      // const class, calls the user-provided default ctor
                  // t2.mem is default-initialized (to indeterminate value)
  std::cout << t2.mem << std::endl;

}

如果我没有为结构T1分配构造函数,编译器必须生成默认构造函数?而struct T2的构造函数是空的初始化列表,为什么它没有错误提示?

c0vxltue

c0vxltue1#

我的理解是,编译器试图保护你免受它自己生成的代码的影响,并在使用你提供的构造函数时假设“你最了解”。此外,检查构造函数是否在任何地方初始化T2.mem,包括在构造函数的主体中,可能是一个任意复杂的任务,因此编译器作者可能认为这是一个最好不要尝试的任务,而不是执行得很差。
如果你将t1声明为const T1,那么MSVC的warning you would get似乎也支持这一点:
用编译器生成的默认构造函数初始化的“const”自动数据产生不可靠的结果
请注意“编译器生成的默认构造函数”这一措辞。
顺便说一句,如果你用T2() = default请求编译器生成的默认构造函数,你会看到同样的警告。

s2j5cfk0

s2j5cfk02#

编译器并不完美。有时候他们警告一件事,但他们不为另一个,类似的事情。许多编译器还提供生成代码的运行时插装,在那里它们插入特殊的指令来检测错误,如使用未初始化的变量,并在发生这种情况时中止程序。但同样,这个系统并不完美,它可能会错过一些东西。
在任何情况下,您实际上都不需要构造函数。你可以内联初始化类成员:

struct T1
{
    int mem = 0;
};

默认情况下,将使用内联初始化,除非构造函数将成员转换为其他内容:

struct T1
{
    int mem = 0;

    T1() = default;

    T1(int m) : mem(m) { }
};
// ...
T1 first; // first.mem == 0
T1 second(1); // second.mem == 1

相关问题