【发布时间】:2018-06-04 19:41:46
【问题描述】:
经过几年的 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 world”的地址.然而,在执行这一行之后,相同的地址只能用于到达字符串/字符“n”。
我的假设是使用 [] 运算符会导致在指定索引之后放置一个空字符。但我无法确认这一点。
例如,在上面使用 ps[0] 的代码中,我尝试打印 ps1, ps[2] 只是为了看看会发生什么。
我在输出中得到的要么是看起来像空格的无休止(空)输出,要么是一堆乱码。我的空字符假设似乎并非如此。为了更好地衡量,我还尝试在 ps[10] 之类的某个位置手动放置一个空字符,但出现分段错误..之前分配给我的字符串的内存超出了范围!
所以,看来我需要对这个主题进行一个很好的修改,有人可以解释发生了什么吗?如果此问题中的某些内容含糊不清或表达不当,请随时告诉我,我会尽力解决。
【问题讨论】:
-
不要使用
string*。只需直接使用string。你没有调用string::operator[],而是内置的[]指针运算符 -
您需要先尊重指针,然后才能调用运算符或使用看起来很傻的语法。例如:
(*ps)[0] = 'n';但更喜欢不使用指针或原始动态分配。 -
对于任何数组或指针
p和索引i,表达式p[i]等于*(p + i)。使用ps[0],您将取消引用指针ps,以获取它指向的“数组”中的第一个元素。它等于*ps = 'n'。