Разница между оператором std :: string [] и at () - PullRequest
0 голосов
/ 04 июня 2018

Я возвращаюсь к C ++ после нескольких лет C #, Javascript, веб-разработки и т. Д.

Есть нить, где объясняется, что основное различие между ними заключается в том, что метод at () делает границыпроверяет и выдает исключение, если указанный индекс выходит за границы.

В чем разница между string :: at и 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', то после проверки переменной ps она, по-видимому, хранит адрес, который используется для достижения строки "Hello world".Однако после выполнения этой строки один и тот же адрес может использоваться только для достижения строки / символа «n».

Моя гипотеза заключалась в том, что использование оператора [] приводит к тому, что нулевой символ помещается сразу после указанного индекса..но мне не удалось это подтвердить.

например, в приведенном выше коде с помощью ps [0] я попытался напечатать ps 1 , ps [2], чтобы посмотреть, чтопридет.

То, что я получил на выходе, это либо бесконечный (пустой) вывод того, что казалось пробелами, либо куча тарабарщины.Похоже, для моей гипотезы нулевого характера не быть так.В качестве меры предосторожности я также попытался вручную поместить нулевой символ в какую-то позицию, например ps [10], но получил ошибку сегментации ... память, ранее выделенная для моей строки, вышла за пределы!

Итак, этоПохоже, мне нужна хорошая ревизия на эту тему, может кто-нибудь объяснить, что происходит?Пожалуйста, не стесняйтесь, дайте мне знать, если что-то в этом вопросе расплывчато или плохо выражено, я сделаю все возможное, чтобы это исправить.

1 Ответ

0 голосов
/ 04 июня 2018

Ваша вторая программа искажена.Он вообще не использует 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;
}

Или, иными словами, используйте это вместо:

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...