2012-04-11 58 views
7

下面是一些示例代码:按值传递容器是否使迭代器无效?

#include <iostream> 
#include <vector> 

template <typename T> 
std::vector<typename T::iterator> f(T t) 
{ 
     std::vector<typename T::iterator> v; 
     for (auto i = t.begin(); i != t.end(); ++i) 
     { 
       v.push_back(i); 
     } 
     return v; 
} 

template <typename T> 
void print(const std::vector<T>& v) 
{ 
     for (auto i = v.begin(); i != v.end(); ++i) 
     { 
       std::cout << **i << ' '; 
     } 
     std::cout << std::endl; 
} 

int main() 
{ 
     std::vector<int> v{1, 2, 3}; 
     print(f(v)); 
     std::vector<std::vector<int>::iterator> itervec = f(v); 
     print(itervec); 
} 

ideone产量为:

1 2 3 
163487776 2 3 

问题

如果我改变f(T t)f(T& t)的输出为预期。我假设,因为我正在处理容器的副本,技术上我推回的矢量上的迭代器与我在main中创建的矢量不一样。它是否正确? 我注意到的一件事是print(f(v));打印1 2 3按预期,但只要我将它分配给itervec第一个迭代器变成垃圾,这是所有的实现相关吗?

回答

8

是的,迭代器迭代器仅在功能f本地对象v有效,并在f末,v超出范围并销毁,而迭代器是无效的。

您必须通过引用(或指针或其他)传递向量,以便您存储的迭代器是调用者传入的原始对象的迭代器,而不是存储在局部变量中的临时副本。

您看到的行为是未定义的,所以它只是正确地打印前三个和后两个。

3

是的,因为您正在接收临时数据并返回该临时数据的迭代器。函数退出后,临时数据被清理,使迭代器无效。

如果您通过参考mainprint都访问相同的对象。由于此对象在函数退出后仍然存在,所以迭代器不会失效。