用'auto'和 std::minmax 观察奇怪的行为



我在SUSE Enterprise Linux 11上使用GCC 4.7.2和Boost 1.58.0。我有下面的代码片段,它基本上通过多边形列表来计算它们的长度/宽度。在std::minmax函数中使用"auto"关键字时,我看到了奇怪的输出。为了进行比较,我还声明了第二个变量,其中明确声明了类型(即dim与dim1)。

namespace gtl = boost::polygon;
typedef gtl::polygon_90_data<int> LayoutPolygon;
typedef gtl::rectangle_data<int> LayoutRectangle;
static LayoutFeatureVec
calc_stats(LayoutPolygonSet const& lp)
{
   LayoutFeatureVec v;
   LayoutFeature f;
   LayoutRectangle y;
   for (LayoutPolygon const& p : lp) {
      // Compute bounds.
      gtl::extents(y, p);
      // Get width/length (shorter/longer).
      // FIXME: Why does this not work with auto??
      cout << gtl::delta(y, gtl::HORIZONTAL) << " " << gtl::delta(y, gtl::VERTICAL) << endl;
      auto dim = std::minmax(gtl::delta(y, gtl::HORIZONTAL),
                             gtl::delta(y, gtl::VERTICAL));
      std::pair<int, int> dim1 = std::minmax(gtl::delta(y, gtl::HORIZONTAL),
                                             gtl::delta(y, gtl::VERTICAL));
      cout << dim.first << " " << dim.second << endl;
      cout << dim1.first << " " << dim1.second << endl;
      <snip>
      v.push_back(f);
   }
   return v;
}

对于这个循环的第一次迭代,预期的输出是正确的。

380 420
380 420
380 420

然而,如果我注释掉"dim1"并重新运行相同的代码(即,只使用auto-dim),我会得到std::minmax的奇怪结果。

380 420
140737295994126 140737295994126

我在这里做错了什么?

这是一个最小的例子(根据下面的答案编辑)。

#include <iostream>
#include <algorithm>
#include <boost/polygon/polygon.hpp>
using namespace std;
namespace gtl = boost::polygon;
using namespace gtl::operators;
int main(int argc, char** argv)
{
    gtl::rectangle_data<int> x(0,0,5,5);
    auto dim = std::minmax(gtl::delta(x, gtl::HORIZONTAL), gtl::delta(x, gtl::VERTICAL));
    cout << dim.first << " " << dim.second << endl;
    return 0;
}

这是使用auto作为类型说明符的情况之一。std::minmax返回一对引用:

template< class T > 
std::pair<const T&,const T&> minmax( const T& a, const T& b );

这就是auto的推论。但是delta()返回一个临时的。所以当你写:

auto dim = std::minmax(gtl::delta(y, gtl::HORIZONTAL),
                       gtl::delta(y, gtl::VERTICAL));

dim持有两个悬空引用。但是当你写的时候:

std::pair<int, int> dim1 = std::minmax(...);

你只是直接持有价值观。这就是为什么这是有效的,但auto没有。您正在执行的额外转换可以防止您持有悬空引用。


或者,为了完整性,您可以使用不返回引用的minmax的不同重载:

template< class T >
std::pair<T,T> minmax( std::initializer_list<T> ilist);

只需要一些额外的支架:

auto dim2 = std::minmax({gtl::delta(y, gtl::HORIZONTAL),
                         gtl::delta(y, gtl::VERTICAL)});

但我建议只是明确地命名类型。这对我来说似乎不太容易出错。

相关内容

  • 没有找到相关文章

最新更新