C++的范围for和python的for
python使用for对可迭代对象进行遍历的时候会对原对象进行拷贝,从而当你在循环过程中更改原对象是无法更改循环的行为的,但最后你可以成功地修改原对象
>>>s = "string"
>>>for c in s:
... print(c)
... s = "klllwe"
s
t
r
i
n
g
>>> s
'klllwe'
当然,修改每一步的元素是无法修改原对象的,因为这是拷贝对象中的元素
>>>s = list('string')
>>>for c in s:
print(c)
c = 'd'
s
t
r
i
n
g
>>> s
['s', 't', 'r', 'i', 'n', 'g']
c++中却有些不同,对于string对象,当修改对象时,会影响到循环的输出
#include<iostream>
#include<string>
using namespace std;
int main(int argc, char const *argv[])
{
string s;
cin >> s;
for(auto &c:s){
cout << "next char:";
cout << c<< endl;
s = "a";
}
cout << "string:" << endl;
cout << s << endl;
return 0;
}
werty
next char:w
next char:
next char:r
next char:t
next char:y
string:
a
但有趣的是,即便原对象被改变了,终止条件还是不变的,循环总是会在输出原字符串长度个字符后结束
#include<iostream>
#include<string>
using namespace std;
int main(int argc, char const *argv[])
{
string s;
cin >> s;
for(auto &c:s){
cout << "next char:";
cout << c<< endl;
s = "aaaaaaaaaaaa";
}
cout << "string:" << endl;
cout << s << endl;
return 0;
}
wwk
next char:w
next char:a
next char:a
string:
aaaaaaaaaaaa
奇怪的是当修改后的字符串长度超过16后,除了第一个字符外,其他输出均为空
#include<iostream>
#include<string>
using namespace std;
int main(int argc, char const *argv[])
{
string s;
cin >> s;
for(auto &c:s){
cout << "next char:";
cout << c<< endl;
s = "adwwwwwwwwwwwwwd";
}
cout << "string:" << endl;
cout << s << endl;
return 0;
}
kkkkk
next char:k
next char:
next char:
next char:
next char:
string:
adwwwwwwwwwwwwwd
当初始输入的字符串较长的时候,发现中间断层
abcdefghijk
next char:a
next char:
next char:
next char:
next char:
next char:
next char:
next char:
next char:i
next char:j
next char:k
string:
adwwwwwwwwwwwwwd
输入再长一点,问题就消失了
kkkkkkkkkkkkkkkkk
next char:k
next char:d
next char:w
next char:w
next char:w
next char:w
next char:w
next char:w
next char:w
next char:w
next char:w
next char:w
next char:w
next char:w
next char:w
next char:d
next char:
string:
adwwwwwwwwwwwwwd
真是比女朋友还难以琢磨(虽然我没有)
这个故事告诉我们,在循环中更改被迭代的对象(尤其是其长度)会产生无法预料(按照c++ primer的常用说法)的结果,这是因为,范围for的等价语句为
for(auto beg=v.begin(),end=v.end();beg!=end;++beg){
;
}
,不过c++中可以通过更改c的方式来更改s
#include<iostream>
#include<string>
using namespace std;
int main(int argc, char const *argv[])
{
string s;
cin >> s;
for(auto &c:s){
c = 'X';
}
cout << s << endl;
return 0;
}
asdasd
XXXXX
只要声明c为引用即可,如果没有声明c是引用,结果就和python中试图修改迭代对象的元素一样,修改的只是复制的元素,最后原对象是不变的