模板函数的不同结果取决于引用类型

时间:2013-11-29 05:12:47

标签: c++ c++11

我正在创建一个包含两个迭代器的简单结构,我可以使用基于范围的循环。

#include <vector>
#include <iostream>
#include <utility>

template <class TIterator>
struct Range
{
 Range(const TIterator &begin, const TIterator &end)
     :_begin(begin), _end(end) {}

 TIterator begin() { return _begin; }
 TIterator end() { return _end; }

private:
 TIterator _begin;
 TIterator _end;
};

template <class TRange>
auto make_range(TRange r) -> Range<decltype(std::begin(r))>
{
    return { std::begin(r), std::end(r) };   
}

template <class TRange>
auto make_range2(TRange &r) -> Range<decltype(std::begin(r))>
{
    return { std::begin(r), std::end(r) };   
}


int main()
{
    std::vector<int> vec = {1,2,3,4,5};
    auto r = make_range(vec);

    for (auto i : r)
    {
        std::cout << i << std::endl;   // 0 0 3 4 5 or 0 2 3 4 5 depends on compiler
    }

    std::vector<int> vec2 = {1,2,3,4,5};
    auto r2 = make_range2(vec2);

    for (auto i : r2)
    {
        std::cout << i << std::endl;   // 1 2 3 4 5
    }

    return 0;
}

第一个循环打印出0 0 3 4 50 2 3 4 5(意外)和第二个循环打印1 2 3 4 5(正如预期的那样)

有人可以向我解释为什么make_range没有给出正确的价值吗?它如何产生0 0 3 4 50 2 3 4 5?我是否使用了任何未定义的行为,或者这是编译器错误?

实时示例:ColiruIdeone

2 个答案:

答案 0 :(得分:2)

make_range按值获取其参数。 r是一个临时函数,在函数返回时被销毁,使所有迭代器无效。随后的解除引用尝试表示迭代器表现出不确定的行为。

答案 1 :(得分:1)

在make_range(TRange r)中,r是向量的本地副本,它超出了作用域,使迭代器无效。