Почему объект std :: string при построении с конструктором по умолчанию ведет себя иначе? - PullRequest
3 голосов
/ 11 ноября 2019

Я попробовал следующую программу:

#include <iostream>
#include <string>

int main ()
{
  std::string str;
  str[0] = 'o';
  str[1] = 'k';
  std::cout << str.length();
  std::cout << "as a whole :";
  std::cout << str << std::endl;
  std::cout << "character by character :";
  std::cout << str[0] << str[1] << std::endl;      
  return 0;
}

Я не понимаю, почему я не могу напечатать строку целиком, используя переменную объекта, и почему длина возвращается как 0, поскольку ясно, что у меня естьдобавил символы, используя оператор нижнего индекса, так как это возвращает ссылку на символ, так что я знаю, что это допустимо.

Кроме того, я не получил никакого исключения. Так что это так. Очевидно, что в классе std::string много чего происходит, и я знаю, что что-то упустил. Может ли кто-нибудь помочь мне с этим?

Ответы [ 3 ]

5 голосов
/ 11 ноября 2019

У вас есть строка длиной 0, а затем вы пытаетесь изменить ее содержимое, используя оператор индекса. Это неопределенное поведение, поэтому на данный момент никакой конкретный результат не гарантирован. Если бы вместо этого вы использовали at(), он бы выявил ошибку и вместо этого выдал исключение.

, почему длина возвращается как 0

Она началась как 0 и вы ничего не сделали, чтобы добавить к нему (например, push_back или +=). Но опять же, поскольку то, что вы делали ранее, было неопределенным поведением, здесь могло произойти все что угодно.

Кроме того, я не получил никаких исключений.

Вместо этого вы можете попробовать std::string::at, что вызовет исключение std::out_of_range, когда вы попробуете это.

5 голосов
/ 11 ноября 2019

Я не понимаю, почему я не могу напечатать строку целиком [...] ...

Поскольку вы испытываете неопределенное поведение 1006 *.

Этот

std::string str;

создает строку по умолчанию с 0 выделениями памяти. Значение, изменяемое с помощью std::string::operator[], вызовет оценки за пределами неопределенного поведения . Поэтому все может случиться. В вашем случае длина возвращается 0.


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

Нет , у вас нет, по вышеуказанной причине. Для справки, std::string::operator[]

Возвращает ссылку на символ в указанном месте поз. Нет Проверка границ выполняется. Если pos> size (), поведение не определено.


В качестве возможных исправлений вы можете захотеть std::string::resize перед доступом к элементам.

#include <string>

std::string str;
str.resize(2);
str[0] = 'o';
str[1] = 'k';
// ... now it has defined behaviour

или std::string::push_back каждый указатель в строку.

#include <string>

std::string str;
str.push_back('o');
str.push_back('k');
// ... now it has defined behaviour
3 голосов
/ 11 ноября 2019

Вы ничего не добавили к пустой строке str. Вместо этого вы пытаетесь редактировать несуществующий элемент пустой строки. Подстрочный оператор std::string не добавляет элемент автоматически. (в отличие от std::map). Кроме того, не гарантируется, что оператор подстрочного индекса выдает некоторое исключение. Если вы хотите safe-subscript-operation , вы можете использовать функцию std::string::at.

Вы можете использовать оператор += для добавления чего-либо в вашу строку.

str += 'o';
str += 'k';
...