警告:在此函数中使用未初始化的“<anonymous>”[-Wuninitialized]

Mat*_*att 6 c++

以下程序编译时不会出现警告-O0

\n\n
#include <iostream>\n\nstruct Foo\n{\n  int const& x_;\n  inline operator bool() const { return true; }\n  Foo(int const& x):x_{x} { }\n  Foo(Foo const&) = delete;\n  Foo& operator=(Foo const&) = delete;\n};\n\nint main()\n{\n  if (Foo const& foo = Foo(3))\n    std::cout << foo.x_ << std::endl;\n\n  return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
maybe-uninitialized.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\nmaybe-uninitialized.cpp:15:22: warning: \xe2\x80\x98<anonymous>\xe2\x80\x99 is used uninitialized in this function [-Wuninitialized]\n std::cout << foo.x_ << std::endl;\n
Run Code Online (Sandbox Code Playgroud)\n\n

如何摆脱这个警告-O1

\n\n

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

\n\n

分辨率在底部

\n\n

编辑:

\n\n
$ g++ --version\ng++ (GCC) 8.2.1 20181127\n\nNo warnings:  g++ maybe-uninitialized.cpp -Wall -O0\nWith warning: g++ maybe-uninitialized.cpp -Wall -O1\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑 2 回应@Brian

\n\n
#include <iostream>\n\nstruct CheckEq\n{\n  int const& x_;\n  int const& y_;\n  bool const result_;\n  inline operator bool() const { return !result_; }\n  CheckEq(int const& x, int const &y):x_{x},y_{y},result_{x_ == y_} { }\n  CheckEq(CheckEq const&) = delete;\n  CheckEq& operator=(CheckEq const&) = delete;\n};\n\n#define CHECK_EQ(x, y) if (CheckEq const& check_eq = CheckEq(x,y)) \\\n  std::cout << #x << " != " << #y \\\n    << " (" << check_eq.x_ << " != " << check_eq.y_ << ") "\n\nint main()\n{\n  CHECK_EQ(3,4) << \'\\n\';\n\n  return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

上面的内容更有趣,因为没有警告,但不同的输出取决于-O0-O1

\n\n
g++ maybe-uninitialized.cpp -O0 ; ./a.out\nOutput: 3 != 4 (3 != 4) \n\ng++ maybe-uninitialized.cpp -O1 ; ./a.out\nOutput: 3 != 4 (0 != 0) \n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑 3 - 接受的答案

\n\n

感谢@RyanHaining。

\n\n
#include <iostream>\n\nstruct CheckEq\n{\n  int const& x_;\n  int const& y_;\n  explicit operator bool() const { return !(x_ == y_); }\n};\n\nint f() {\n  std::cout << "f() called." << std::endl;\n  return 3;\n}\n\nint g() {\n  std::cout << "g() called." << std::endl;\n  return 4;\n}\n\n#define CHECK_EQ(x, y) if (CheckEq const& check_eq = CheckEq{(x),(y)}) \\\n  std::cout << #x << " != " << #y \\\n    << " (" << check_eq.x_ << " != " << check_eq.y_ << ") "\n\nint main() {\n  CHECK_EQ(f(),g()) << \'\\n\';\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
f() called.\ng() called.\nf() != g() (3 != 4) \n
Run Code Online (Sandbox Code Playgroud)\n\n

特征:

\n\n
    \n
  • 每个参数CHECK_EQ只检查一次。
  • \n
  • 输出显示内联代码比较以及值。
  • \n
\n

Rya*_*ing 3

虽然具有用户定义构造函数的类无法延长临时构造函数的生命周期,但聚合可以。通过转换为聚合,我可以使你的方法发挥作用

#include <iostream>

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

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

int main() {
  CHECK_EQ(3,4) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

对于我来说,使用和不使用 -O3 都会产生相同的输出