const auto& 使用 std::min std::max 转换为整数

Roy*_*ang 1 c++ c++11

我在下面有这些代码。const auto&在这种情况下有什么问题,它导致了意外的输出。

使用 gcc-4.8.5 编译时它工作正常,但使用 gcc-4.9.2 得到意外输出。

如果我删除&in const auto&,它可以在两个 gcc 版本中正常工作。

// max_dim is a protobuf filed: const auto max_dim = msg.max();
// cat2_num is an element in std::vector<int32_t>: const auto cat2_num = vec[i]
const auto& res_num = std::max(1, std::min(max_dim, cat2_num));
LOG(ERROR) << res_num << ", " << max_dim << ", " << cat2_num
   << ", " << std::max(1, std::min(max_dim, cat2_num));
Run Code Online (Sandbox Code Playgroud)

输出:

 -1392522416, 3, 1, 1
 2, 3, 2, 2
 3, 3, 3, 3
 -1392522416, 3, 1, 1
 3, 3, 6, 3
 2, 3, 2, 2
 -1392522416, 3, 1, 1
 -1392522416, 3, 1, 1
 2, 3, 2, 2
Run Code Online (Sandbox Code Playgroud)

============更新========

我无法使用这些代码重现未定义的行为:

 -1392522416, 3, 1, 1
 2, 3, 2, 2
 3, 3, 3, 3
 -1392522416, 3, 1, 1
 3, 3, 6, 3
 2, 3, 2, 2
 -1392522416, 3, 1, 1
 -1392522416, 3, 1, 1
 2, 3, 2, 2
Run Code Online (Sandbox Code Playgroud)

输出:

1, 3, -1
1, 3, 0
1, 3, 1
2, 3, 2
3, 3, 3
3, 3, 6
Run Code Online (Sandbox Code Playgroud)

Nat*_*ica 10

您的代码具有未定义的行为。在

const auto& res_num = std::max(1, std::min(max_dim, cat2_num));
Run Code Online (Sandbox Code Playgroud)

1是prvalue,所以暂时整数创建获取绑定到函数参数。这会没事的 max 就像

template <typename T> const T max(const T&, const T&);
Run Code Online (Sandbox Code Playgroud)

但相反,它被定义为

template <typename T> const T& max(const T&, const T&);
Run Code Online (Sandbox Code Playgroud)

因此,如果这1恰好是最大值,则max返回对创建的临时对象的引用。之后,临时对象被销毁1res_num作为悬空引用留下。要修复代码,请进行res_num非引用,例如

const auto res_num = std::max(1, std::min(max_dim, cat2_num));
Run Code Online (Sandbox Code Playgroud)

现在你得到了正确值的副本。

1:在完整表达式的末尾销毁所有临时变量,并在其中创建