我们假设我们有一个功能1:
vector<T>::iterator GetSomething()
{
vector<T> vec;
// Update vec with something...
return vec.begin();
}
另一个功能2:
vector<T> GetSomething()
{
vector<T> vec;
// Update vec with something...
return vec;
}
在什么情况下我们更喜欢功能1? 此外,该矢量对象的生命周期是什么? 我们如何知道迭代器是否指向空向量?可能需要传递一对迭代器来确定开始/结束。
答案 0 :(得分:3)
您不应该将迭代器返回到本地分配的向量。这是一种未定义的行为。
解释非常简单:离开函数后,vector<T> vec;
将被销毁。
第二个选项更好,很可能会有返回值优化,它将精确地构造向量。
答案 1 :(得分:1)
向量迭代器仅对它来自的向量有效,因此将迭代器返回到本地向量是没有用的。
当您将其所属的向量作为参数引用传递时,仅返回向量迭代器:
std::vector<int>::iterator find(std::vector<int>& v, int i)
{
// do findie stuff
return std::find(std::begin(v), std::end(v), i);
}
你从不想要这样做:
vector<T>::iterator GetSomething()
{
vector<T> vec;
// Update vec with something...
return vec.begin(); // this iterator will be bad when it arrives
}
一旦向量在函数末尾被销毁,其迭代器就会失效。
答案 2 :(得分:0)
vector的生命周期,就像所有其他自动变量一样,以声明它的块的范围结束。
因此,如果你返回迭代器,它将指向释放的内存,并做各种有趣的事情,比如崩溃你的程序。
如果您返回向量本身,则会复制其所有内容,但原始向量仍会“死亡”。在街区尽头。
答案 3 :(得分:0)
除了关于在堆栈上返回类似指针的一般说法之外,选项1要求一对方法(函数取消限制选项1):begin&amp;结束。 C ++中的迭代器不能像java,python和许多其他人那样工作。
答案 4 :(得分:0)
没有首选您的第一个功能的情况。函数返回时,向量vec
不再存在。该向量提供的任何迭代器对调用者都是无效的。这些迭代器(尤其是解除引用)的大多数用法都会导致调用者表现出未定义的行为。
函数返回迭代器的唯一时间是在函数返回后保证提供这些迭代器的向量。实际上,只有三种情况可以做到这一点。第一种方法是将向量作为参数传递给函数,例如
std::vector<int>::iterator func(std::vector<int> &vec)
{
return vec.begin();
}
由于调用者传递了向量,因此当函数返回时,向量将存在。
第二种情况是,如果向量是静态的,或者在函数返回时继续存在。
std::vector<int>::iterator func(std::vector<int> &vec)
{
static std::vector<int> vec;
return vec.begin();
}
当然,使用这样的函数会产生与静态相关的所有复杂问题(例如,重入问题,需要跨线程同步使用等)。
可以返回迭代器的第三种情况是迭代器是否传递给函数。如
std::vector<int>::iterator func(std::vector<int>::iterator it)
{
return it + 1;
}
在这种情况下,调用者可以传递一个有效的迭代器(例如从它控制的容器中获取),该迭代器可以递增(或提前1)。
此外,如果函数返回迭代器,则调用者可能需要在使用之前检查迭代器是否有效。如果是这样,那应该记录下来。例如,如果函数可能返回一个结束迭代器,则调用者应该在尝试取消引用之前检查,而不是在之后。