【问题标题】:Difference between std::string [] operator and at()std::string [] 运算符和 at() 之间的区别
【发布时间】: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] 之类的某个位置手动放置一个空字符,但出现分段错误..之前分配给我的字符串的内存超出了范围!

所以,看来我需要对这个主题进行一个很好的修改,有人可以解释发生了什么吗?如果此问题中的某些内容含糊不清或表达不当,请随时告诉我,我会尽力解决。

【问题讨论】:

标签: c++ pointers


【解决方案1】:

您的第二个程序格式错误。它根本没有使用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;
}

【讨论】:

  • 为什么不按值传递str 并删除ps
  • 这取决于OP是否想修改str,你不要
  • 除了“为什么这没有达到我的预期?”之外,当然可以对代码进行很多改进。 ...我自己开始滑下那个斜坡。
  • 感谢您的回答。 tbh,我认为这个问题本身是由于我在阅读关于 auto_ptr 的书籍部分时偏离正题而达到的。开题,书上提出了remodel函数(不过只有第一行和我的差不多),然后我就从那里开始往下滑了……
猜你喜欢
  • 2014-09-17
  • 2021-12-28
  • 2011-05-24
  • 2016-05-18
  • 2011-10-22
  • 2012-10-06
  • 2010-10-16
  • 2010-12-30
  • 2019-08-29
相关资源
最近更新 更多