Подтвердить что ты не робот

Добавить int в std::string

Я попробовал два разных способа добавить int в std::string, и, к моему удивлению, у меня были разные результаты:

#include <string>

int main()
{
    std::string s;
    s += 2;     // compiles correctly
    s = s + 2;  // compiler error

    return 0;
}

Почему он компилируется и работает правильно, когда я использую оператор +=, но сбой при использовании оператора +?

Я не думаю, что вопрос похож на Как объединить std::string и int?

В этом вопросе ни один ответ не использует оператор +=. И разница между += и + оператора std::string является ключом к решению моих сомнений.

Откровенно говоря, этот вопрос является хорошим примером для объяснения того, почему С++ настолько сложно освоить.

4b9b3361

Ответ 1

TL; DR operator+= - это функция-член класса в class string, а operator+ - это функция шаблона.

Стандартный класс template<typename CharT> basic_string<CharT> имеет перегруженную функцию basic_string& operator+=(CharT), а строка - это просто basic_string<char>.

Поскольку значения, которые подходят для более низкого типа, могут быть автоматически добавлены в этот тип, в выражении s += 2, 2 не рассматривается как int, а char. Он имеет тот же эффект, что и s += '\x02'. A char с кодом ASCII 2 (STX) добавляется, не символ "2" (с ASCII-значением 50 или 0x32).

Однако строка не имеет перегруженной функции-члена, такой как string operator+(int), s + 2 не является допустимым выражением, поэтому выдает ошибку во время компиляции. (Более подробно)

Вы можете использовать функцию operator + в строке следующими способами:

s = s + char(2); // or (char)2
s = s + std::string(2);
s = s + std::to_string(2); // C++11 and above only

Для людей, обеспокоенных тем, почему 2 не автоматически добавляется к char с помощью operator+,

template <typename CharT>
  basic_string<CharT>
  operator+(const basic_string<CharT>& lhs, CharT rhs);

Вышеописанный прототип [note] для оператора плюс в s + 2, и поскольку он является функцией шаблона, ему требуется реализация как operator+<char>, так и operator+<int>, что противоречиво. Подробнее см. Почему автоматическое подавление применяется к функциям шаблона?

Между тем прототипом operator+= является:

template <typename CharT>
class basic_string{
    basic_string&
      operator+=(CharT _c);
};

Вы видите, здесь нет шаблона (это функция-член класса), поэтому компилятор выводит, что тип CharT char из реализации класса, а int(2) автоматически добавляется в char(2).


Примечание: Ненужный код удаляется при копировании из стандарта С++, включая источник. Это включает в себя typename 2 и 3 (Traits and Allocator) для класса шаблона "basic_string" и ненужные символы подчеркивания, чтобы улучшить читаемость.

Ответ 2

s += 2; не делает то, что, по вашему мнению, делает. Он вызывает перегруженный оператор += до char. Он не добавляет символ '2', а скорее символ со значением 2, и результат будет зависеть от кодировки, используемой на вашей платформе.

Не существует перегрузки оператора, которая позволяет s + 2 скомпилировать 1. Отсюда ошибка.

Решение в обоих случаях заключается в использовании std::to_string(2), а не в литерале int.


1 По сути, причина в том, что operator+= не является функцией шаблона, но std::operator+ есть, а разрешение перегрузки будет поддерживать функцию без шаблона над шаблоном.

Ответ 3

Правильный способ добавить к вашему string будет

std::string s;
s += std::to_string(2);
s = s + std::to_string(2);

Ответ 4

В то время как ответ @CoryKramer дает вам правильный способ добавить целое число в строку, он не объясняет, почему команда s = s + 2 не компилируется.

Разница между двумя инструкциями заключается в том, что в первом вы используете std::string + = operator, а во второй инструкции, компилятор пытается передать 2 в строку.

Нет никакого неявного преобразования между int и std::string. однако вы можете отбрасывать int в char, поэтому именно поэтому работает s += 2.