使用 'auto' 和 std::minmax 观察奇怪的行为
Observing weird behavior with 'auto' and std::minmax
我在 SUSE Enterprise 上使用 GCC 4.7.2 和 Boost 1.58.0 Linux 11. 我有以下代码片段,它基本上遍历多边形列表来计算它们 length/width。在 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' 并重新运行相同的代码(即只有自动变暗),我会得到 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
return一对引用:
template< class T >
std::pair<const T&,const T&> minmax( const T& a, const T& b );
这就是 auto
的推论。但是 delta()
return 是暂时的。所以当你写:
auto dim = std::minmax(gtl::delta(y, gtl::HORIZONTAL),
gtl::delta(y, gtl::VERTICAL));
dim
持有两个悬挂引用。但是当你写:
std::pair<int, int> dim1 = std::minmax(...);
您只是直接持有这些值。这就是为什么它有效但 auto
无效的原因。您正在执行的额外转换可防止您持有悬空引用。
或者,为了完整起见,您可以使用不 return 引用的 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)});
但我建议只明确命名类型。这对我来说似乎不太容易出错。
我在 SUSE Enterprise 上使用 GCC 4.7.2 和 Boost 1.58.0 Linux 11. 我有以下代码片段,它基本上遍历多边形列表来计算它们 length/width。在 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' 并重新运行相同的代码(即只有自动变暗),我会得到 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
return一对引用:
template< class T >
std::pair<const T&,const T&> minmax( const T& a, const T& b );
这就是 auto
的推论。但是 delta()
return 是暂时的。所以当你写:
auto dim = std::minmax(gtl::delta(y, gtl::HORIZONTAL),
gtl::delta(y, gtl::VERTICAL));
dim
持有两个悬挂引用。但是当你写:
std::pair<int, int> dim1 = std::minmax(...);
您只是直接持有这些值。这就是为什么它有效但 auto
无效的原因。您正在执行的额外转换可防止您持有悬空引用。
或者,为了完整起见,您可以使用不 return 引用的 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)});
但我建议只明确命名类型。这对我来说似乎不太容易出错。