boost :: combine()是否可以与方法的输出一起使用?

时间:2019-04-04 08:14:20

标签: c++ boost

在下面的测试案例中,我使用boost :: combine对函数getPoints()的输出进行迭代。

预期产量

我希望(1、2、3)打印6次;因为我有效地压缩了两个列表-

([点,点,点],[点,点,点])。

实际输出

输出令我惊讶,这是错误的。前两行显示暗示内存损坏?

(0, 0, 3)          // <-- wrong!
(52246144, 0, 3)   // <-- wrong! memory corruption?
(1, 2, 3)
(1, 2, 3)
(1, 2, 3)
(1, 2, 3)

也可以在http://cpp.sh/622h4此处在线进行验证。

这是一个错误吗?

下面的代码-

#include <iostream>
#include <vector>

#include <boost/range/combine.hpp>


struct Point {
    int x, y, z;
};

const std::vector<Point> getPoints() {
    // There is only one Point in the entire code, which is (1, 2, 3).
    const Point point = {1, 2, 3};
    // Return a vectore of 3 copies of the point (1, 2, 3).
    return {point, point, point};
}


int main() {
    // Zip over two copies of 3-tuples of {1, 2, 3}.
    for (const auto& zipped : boost::combine(getPoints(), getPoints())) {
        auto p1 = zipped.get<0>();
        auto p2 = zipped.get<1>();
        // Expected output is (1, 2, 3), six times.
        std::cout << "(" << p1.x << ", " << p1.y << ", " << p1.z << ")" << std::endl;
        std::cout << "(" << p2.x << ", " << p2.y << ", " << p2.z << ")" << std::endl;
    }

    return 0;
}

1 个答案:

答案 0 :(得分:2)

在访问悬空参考时,此处的行为不确定。可以通过

解决
const auto points1 = getPoints();
const auto points2 = getPoints();

for (const auto& zipped : boost::combine(points1, points2)) {
    // ...
}

在处理范围库时,右值引用总是有问题的。显然,像boost::combine这样的范围算法不会复制该参数。并且它创建了一个新的代理范围对象,从而无法延长传入的临时范围的寿命。

相反,基于范围的for循环for(const auto& item: getPoints()) {...}扩展为

{
    auto && __range = getPoints();
    for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {

        range_declaration = *__begin;
        loop_statement
    }
} 

其中getPoints()的生存期是通过将其绑定到右值引用来延长的。想象一个功能模板combine

template<class Rng>
auto combine(Rng&& rng) {
    auto && == range; // Nice try but doesn't help

    // ...

    return someProxyRange;
}

此功能模板对延长rng的生存期无能为力,因为它的作用域与rng的作用域不同,后者来自客户端。在基于for的范围内,这是不同的。临时范围(例如getPoints())和转发引用auto&& __range处于相同范围,因此可以延长生存期。