经过几年的C#,Javascript,Web开发等,我正在重温C ++。
有一个线程,其中解释了这些之间的主要区别在于at()方法确实绑定了检查,如果提供的索引超出范围,则抛出异常。
What is the difference between string::at and string::operator[]?
然而,这似乎不能证明我遇到的以下行为是正当的,也许有人可以帮助我?
#include <iostream>
#include <string>
using namespace std;
void remodel(string & str){
string * ps = new string(str);
ps->at(0) = 'n';
cout<<*ps<<endl;
delete ps;
}
int main(){
string str = "Hello world";
remodel(str);
cin.get();
return 0;
}
nello world
在上面的代码中,我使用at()方法来更改字符串的第一个字符,并且我成功地能够这样做。打印字符串确认了这一点。
使用[]运算符时会发生不同的事情:
#include <iostream>
#include <string>
using namespace std;
void remodel(string & str){
string * ps = new string(str);
ps[0] = 'n';
cout<<*ps<<endl;
delete ps;
}
int main(){
string str = "Hello world";
remodel(str);
cin.get();
return 0;
}
n
在上面的代码中,在索引0上使用[]运算符会用字母'n'替换整个字符串。这在调试器中得到了证实,我可以看到从“Hello world”到“n”的完全重新分配值
只是详细说明,如果我放置一个断点使程序在执行ps [0] ='n'之前停止,那么在inspecting the variable ps上,它似乎存储了一个用于到达字符串“Hello”的地址世界”。但是,执行此行后,相同的地址只能用于到达字符串/字符“n”。
我的假设是使用[]运算符导致在指定的索引之后放置一个空字符。但我无法确认这一点。
例如,在上面的代码中使用ps [0]我试图打印ps 1,ps [2]只是为了看看会发生什么。
我输出的是输出看似空间的无尽(空)输出,或者是一堆乱码。对于我的空字符假设似乎并非如此。为了更好的衡量,我还尝试手动将空字符放在某个位置,如ps [10],但是出现了分段错误。之前分配给我的字符串的内存超出了界限!
所以,看来我需要对这个主题做一个很好的修改,有人可以解释一下吗?如果这个问题中的某些内容含糊不清或表达不好,请随时告诉我,我会尽力解决。
答案 0 :(得分:3)
您的第二个程序格式错误。它根本没有使用std::string::operator[]
。
string * ps = new string(str);
ps[0] = 'n';
std::string
不仅支持[]
运算符,每个指向类型的指针也支持[]
运算符。这就是C样式数组的工作方式,而这正是您在上面的代码中所做的。
ps
不是string
。这是一个指针。 ps[0]
是一个字符串,与*ps
不同。
你可能想要this代替:
#include <iostream>
#include <string>
using namespace std;
void remodel(string & str){
string * ps = new string(str);
(*ps)[0] = 'n';
// or: ps->operator[](0) = 'n';
cout<<*ps<<endl;
delete ps;
}
int main(){
string str = "Hello world";
remodel(str);
cin.get();
return 0;
}
或者,更具惯用性,请改用this:
#include <iostream>
#include <string>
using namespace std;
void remodel(string & str){
string ps = str;
ps[0] = 'n';
cout<<ps<<endl;
}
int main(){
string str = "Hello world";
remodel(str);
cin.get();
return 0;
}