为什么这种初始化本身不会产生编译器警告?

问题描述

在此示例中,我有两个类:Test和Test2。他们的两个构造函数都错误地从自身初始化成员变量“ val_”,而不是从预期的参数“ val”初始化成员变量。区别在于Test使用{}语法初始化,而Test2使用()语法初始化。仅Test2的初始化会生成“已自身初始化”警告。

我正在使用-Wall进行编译,这意味着-Winit-from-self。从打印结果可以看出,两个构造函数都为_val打印了错误的值。

909> cat initSelfTest.cc
#include <iostream>

using namespace std;

class Test {
public:
    Test (int val);
private:
    int val_;
};
Test::Test (int val) 
    : val_ {val_}
{
    cerr << "Test::Test; val = " << val << "; val_ = " << val_ << "\n";
}

class Test2 {
public:
    Test2 (int val);
private:
    int val_;
};
Test2::Test2 (int val) 
    : val_ (val_)
{
    cerr << "Test2::Test2; val = " << val << "; val_ = " << val_ << "\n";
}

int main (int argc,char **argv) {
    Test test {781981};
    Test2 test2 {781981};
}
910> gcc --version
gcc (GCC) 8.2.0
Copyright (C) 2018 Free Software Foundation,Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

911> g++ -Wall -o initSelfTest initSelfTest.cc
initSelfTest.cc: In constructor ‘Test2::Test2(int)’:
initSelfTest.cc:23:1: warning: ‘Test2::val_’ is initialized with itself [-Winit-self]
 Test2::Test2 (int val)
 ^~~~~
initSelfTest.cc: In constructor ‘Test::Test(int)’:
initSelfTest.cc:12:13: warning: ‘*<unknown>.Test::val_’ is used uninitialized in this function [-Wuninitialized]
     : val_ {val_}
             ^~~~
initSelfTest.cc: In constructor ‘Test2::Test2(int)’:
initSelfTest.cc:24:13: warning: ‘*<unknown>.Test2::val_’ is used uninitialized in this function [-Wuninitialized]
     : val_ (val_)
             ^~~~
912> ./initSelfTest 
Test::Test; val = 781981; val_ = 0
Test2::Test2; val = 781981; val_ = 0
913> 

解决方法

您正在使用该值进行初始化之前,这是未定义的行为,不需要/保证没有错误消息。通常,标准不要求警告。

对于“为什么UB不是错误?”我只能推测。考虑到有些情况看起来非常相似,但是完全可以。例如

struct foo {
  foo& f;
};

foo f{f};

仅取消引用会导致问题,但是可以存储引用以供以后使用。我可以想象,除了邪恶的情况之外,编译器通常无法分辨出这种有效的情况。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...