我正在创建一个包含两个迭代器的简单结构,我可以使用基于范围的循环。
#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 5
或0 2 3 4 5
(意外)和第二个循环打印1 2 3 4 5
(正如预期的那样)
有人可以向我解释为什么make_range
没有给出正确的价值吗?它如何产生0 0 3 4 5
或0 2 3 4 5
?我是否使用了任何未定义的行为,或者这是编译器错误?
答案 0 :(得分:2)
make_range
按值获取其参数。 r
是一个临时函数,在函数返回时被销毁,使所有迭代器无效。随后的解除引用尝试表示迭代器表现出不确定的行为。
答案 1 :(得分:1)
在make_range(TRange r)中,r是向量的本地副本,它超出了作用域,使迭代器无效。