Рекомендации для новичков о том, как избежать ошибок при перегрузке оператора

У меня возник вопрос от моего ученика, спрашивающего, почему следующий код приводит к таинственным выводам.

Код:

#include <iostream>

int main() {
    char op = '+';
    int num = 9;
    std::string res =
        "a const char* concatenated with a char and std::string " 
                    + op + std::to_string(num);
    std::cout << res << std::endl;
}

Ну, он ожидал получить: a const char* concatenated with a char and std::string + 9 и не мог понять, почему он получает всего std::string 9. Понятно, что если бы это был вызов функции, а не оператор, проблема сразу исчезла бы.

Любые советы, которые я могу дать новичкам, как избежать таких ошибок при перегрузке оператора?

Ответ 1

"a const char* concatenated with a char and std::string " является const char[] литералом, а не std::string. Добавление целого числа (char - небольшое целое число) в массив C-стиля генерирует временный указатель, указывающий на этот массив при нумерованном смещении.

Общие рекомендации, чтобы избежать такой проблемы: избегайте использования массивов в стиле C (включая строковые литералы в стиле C).

Вы можете использовать строковый литерал С++:

using namespace std::string_literals;   // need once in the code

std::string res =
    "a const char* concatenated with a char and std::string "s
                + op + std::to_string(num);

Обратите внимание на s в конце литерала. Вам понадобится #include <string> - оригинальная программа тоже должна была это сделать.


Если вы используете старый компилятор, который не поддерживает литералы std::string, то построение строки также может быть выполнено путем потоковой передачи в буфер памяти:

std::ostringstream buffer;
buffer << "bla bla bla" << op << num;
std::string res = buffer.str();