提问人:troppapolvere 提问时间:9/30/2022 最后编辑:Adrian Moletroppapolvere 更新时间:9/30/2022 访问量:87
关于迭代 std::vector 的 C++ 问题
C++ question about iterating over std::vector
问:
我的问题(“为什么它不起作用?”)涉及下面的小样本。
当我运行这个(之后)时,我得到:g++ testThis.cc -o testThis
printing 101
printing 102
printing 103
printing 100
printing 100
printing -1021296524
这应该不是超出范围的问题,那么为什么要制作向量本身的本地副本呢?myHolder
它应该在课堂上保持舒适。
#include <vector>
#include <iostream>
class stdHolder {
public:
stdHolder();
std::vector<int> getSV() const {return _myVector;}
private:
std::vector<int> _myVector;
};
stdHolder::stdHolder() {
_myVector.push_back(1);
_myVector.push_back(2);
_myVector.push_back(3);
}
int main() {
stdHolder myHolder;
// the following works
std::vector<int> localSV = myHolder.getSV();
for (std::vector<int>::iterator it = localSV.begin(); it != localSV.end(); it++ ) {
std::cout << "printing " << *it + 100 << std::endl;
}
//return 0; // comment this line to see my problem
// the following loops forever
for (std::vector<int>::iterator it = myHolder.getSV().begin(); it != myHolder.getSV().end(); it++ ) {
std::cout << " printing " << *it + 100 << std::endl;
}
return 0;
答:
3赞
user12002570
9/30/2022
#1
我的问题(“为什么它不起作用?
因为和处理不同的向量,因为你要调用成员函数两次,并且每次调用都会返回一个不同的向量(因为你按值返回一个向量)。myHolder.getSV().begin()
myHolder.getSV().end()
stdHolder::getSV()
也就是说,迭代器是用 初始化的,但随后您正在比较(双关语),其结果是迭代器与调用返回的完全不同的向量。it
myHolder.getSV().begin()
it
myHolder.getSV().end()
myHolder.getSV()
解决此问题的一种方法是通过常量引用返回向量。这样,第一个循环将从返回值复制,而第二个循环将正常工作,因为它将从相同的向量数据成员中获取迭代器。请注意,如果您使用它,那么对于第二个循环,您必须制作一个 .it
const_iterator
请参阅以下修改程序中的注释:
class stdHolder {
public:
stdHolder();
//-----------------------v---------------------------------->return by const lvalue reference
const std::vector<int> &getSV() const {return _myVector;}
private:
std::vector<int> _myVector;
};
stdHolder::stdHolder() {
_myVector.push_back(1);
_myVector.push_back(2);
_myVector.push_back(3);
}
int main() {
stdHolder myHolder;
//still works
std::vector<int> localSV = myHolder.getSV();
for (std::vector<int>::iterator it = localSV.begin(); it != localSV.end(); it++ ) {
std::cout << "printing " << *it + 100 << std::endl;
}
//this works too now
//---------------------vvvvvvvvvvvvvv--------------------------------------->const_iterator used instead of iterator
for (std::vector<int>::const_iterator it = myHolder.getSV().begin(); it != myHolder.getSV().end(); it++ ) {
std::cout << " printing " << *it + 100 << std::endl;
}
return 0;
}
另一个选择是只为你添加和成员函数,然后你就可以使用基于范围的for循环。begin
end
stdHolder
评论
0赞
ShadowRanger
9/30/2022
一个合理的解决方法可能是通过引用返回。第一个循环将从该返回值复制,而后一个循环是可以的,因为它会让迭代器脱离对同一基础的相同引用。 不是必需的,但它可以防止在界面上打孔,从而允许用户任意修改私有成员。getSV
const
vector
const
0赞
user12002570
9/30/2022
@ShadowRanger 是的,但请注意,对于第二个循环,then 应更改为 .只是在OP不知道这一点的情况下提及。it
const_iterator
0赞
ShadowRanger
9/30/2022
确定。虽然基本上是为了避免声明特定的迭代器类型而引起的恶化,所以除非你以某种方式被限制在 C++ 11 之前(如果是这样,我很可怜你),这不是你通常需要担心的事情。(当然,在这种情况下,普通的 for-each 样式循环也可以消除这种头痛)auto
0赞
user12002570
9/30/2022
@ShadowRanger是的,其他选项是添加和成员函数。begin
end
1赞
troppapolvere
9/30/2022
我今天学到了一些东西!:-)
评论
myHolder.getSV().begin()
并在不同的向量上工作。myHolder.getSV().end()
getSV()
返回一个副本 - 因此每次调用此函数时都会获得一个新的向量。更改返回类型以查看其正常工作std::vector<int>&
begin()
end()
stdHolder
.end()
end()