首页 > 解决方案 > 警告:“<匿名>”在此函数中未初始化 [-Wuninitialized]

问题描述

以下程序编译时没有警告-O0

#include <iostream>

struct Foo
{
  int const& x_;
  inline operator bool() const { return true; }
  Foo(int const& x):x_{x} { }
  Foo(Foo const&) = delete;
  Foo& operator=(Foo const&) = delete;
};

int main()
{
  if (Foo const& foo = Foo(3))
    std::cout << foo.x_ << std::endl;

  return 0;
}

但是,使用-O1或更高时,它会发出警告:

maybe-uninitialized.cpp: In function ‘int main()’:
maybe-uninitialized.cpp:15:22: warning: ‘&lt;anonymous>’ is used uninitialized in this function [-Wuninitialized]
 std::cout << foo.x_ << std::endl;

你如何摆脱这个警告-O1和更高?

这样做的动机是CHECK(x)宏必须捕获一个常量引用而不是一个值,以免触发析构函数、复制构造函数等以及打印出一个值。

分辨率在底部

编辑:

$ g++ --version
g++ (GCC) 8.2.1 20181127

No warnings:  g++ maybe-uninitialized.cpp -Wall -O0
With warning: g++ maybe-uninitialized.cpp -Wall -O1

编辑 2 以回应@Brian

#include <iostream>

struct CheckEq
{
  int const& x_;
  int const& y_;
  bool const result_;
  inline operator bool() const { return !result_; }
  CheckEq(int const& x, int const &y):x_{x},y_{y},result_{x_ == y_} { }
  CheckEq(CheckEq const&) = delete;
  CheckEq& operator=(CheckEq const&) = delete;
};

#define CHECK_EQ(x, y) if (CheckEq const& check_eq = CheckEq(x,y)) \
  std::cout << #x << " != " << #y \
    << " (" << check_eq.x_ << " != " << check_eq.y_ << ") "

int main()
{
  CHECK_EQ(3,4) << '\n';

  return 0;
}

上面更有趣的是没有警告,但输出取决于-O0or -O1

g++ maybe-uninitialized.cpp -O0 ; ./a.out
Output: 3 != 4 (3 != 4) 

g++ maybe-uninitialized.cpp -O1 ; ./a.out
Output: 3 != 4 (0 != 0) 

编辑 3 - 接受的答案

感谢@RyanHaining。

#include <iostream>

struct CheckEq
{
  int const& x_;
  int const& y_;
  explicit operator bool() const { return !(x_ == y_); }
};

int f() {
  std::cout << "f() called." << std::endl;
  return 3;
}

int g() {
  std::cout << "g() called." << std::endl;
  return 4;
}

#define CHECK_EQ(x, y) if (CheckEq const& check_eq = CheckEq{(x),(y)}) \
  std::cout << #x << " != " << #y \
    << " (" << check_eq.x_ << " != " << check_eq.y_ << ") "

int main() {
  CHECK_EQ(f(),g()) << '\n';
}

输出:

f() called.
g() called.
f() != g() (3 != 4) 

特征:

标签: c++

解决方案


该代码具有未定义的行为。调用Foo的构造函数会导致prvalue3作为一个临时对象具体化,该对象绑定到参数x。但是,该临时对象的生命周期在构造函数退出时结束,并在评估x_时作为悬空引用留下。foo.x_

您需要提供有关您希望CHECK宏如何工作的更多详细信息,然后才能建议一种实现它的方法,而无需执行您在此处所做的事情。


推荐阅读