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

Объединение двух строковых литералов

Я очень новичок в программировании и читаю "Ускоренный С++" от Koenig. В любом случае, я изучаю строки, и он пишет, что "новая идея заключается в том, что мы можем использовать + для конкатенации строки и строкового литерала - или, если на то пошло, две строки (но не две строковые литералы).

Хорошо, это имеет смысл, я полагаю. Теперь на два отдельных упражнения, предназначенных для освещения этого.

Имеются ли следующие определения?

const string hello = "Hello";

const string message = hello + ",world" + "!";

Теперь я попытался выполнить выше, и это сработало! Поэтому я был счастлив.

Затем я попытался выполнить следующее упражнение;

const string exclam = "!";

const string message = "Hello" + ",world" + exclam;

Это не сработало. Теперь я понимаю, что это связано с тем, что вы не можете конкатенировать два строковых литерала, но я не понимаю семантической разницы между тем, почему мне удалось получить первый пример для работы (это не "мир" и "!" Два строковых литерала? Не могли бы это не сработать?), но не второй.

Спасибо!

4b9b3361

Ответ 1

const string message = "Hello" + ",world" + exclam;

Оператор + имеет ассоциативность слева направо, поэтому эквивалентное выражение в скобках:

const string message = (("Hello" + ",world") + exclam);

Как вы можете видеть, сначала записываются два строковых литерала "Hello" и ",world", следовательно, ошибка.

Одна из первых двух конкатенированных строк должна быть std::string объектом:

const string message = string("Hello") + ",world" + exclam;

В качестве альтернативы вы можете принудительно оценить второй +, заключая в скобки эту часть выражения:

const string message = "Hello" + (",world" + exclam);

Имеет смысл, что ваш первый пример (hello + ",world" + "!") работает, потому что std::string (hello) является одним из аргументов в самом левом +. Этот + оценивается, результатом является объект std::string с конкатенированной строкой, и итоговое std::string затем объединяется с "!".


Что касается того, почему вы не можете конкатенировать два строковых литерала с помощью +, это потому, что строковый литерал - это просто массив символов (a const char [N] где N - длина строки плюс одна, для нулевой ограничитель). Когда вы используете массив в большинстве контекстов, он преобразуется в указатель на его исходный элемент.

Итак, когда вы пытаетесь сделать "Hello" + ",world", то, что вы действительно пытаетесь сделать, это добавить два const char* вместе, что невозможно (что бы это означало добавить два указателя вместе?), и если это было бы не так, как вы этого хотели.


Обратите внимание, что вы можете конкатенировать строковые литералы, помещая их рядом друг с другом; например, следующие два эквивалентны:

"Hello" ",world"
"Hello,world"

Это полезно, если у вас длинный строковый литерал, который вы хотите разбить на несколько строк. Однако они должны быть строковыми литералами: это не будет работать с указателями const char* или const char[N].

Ответ 2

Вы всегда должны обратить внимание на типы.

Хотя все они кажутся строками, "Hello" и ",world" являются литералами.

И в вашем примере exclam является объектом std::string.

С++ имеет перегрузку оператора, которая принимает объект std::string и добавляет к нему другую строку. Когда вы объединяете объект std::string с литералом, он сделает соответствующее литье для литерала.

Но если вы попытаетесь объединить два литерала, компилятор не сможет найти оператора, который принимает два литерала.

Ответ 3

Второй пример не работает, потому что для двух строковых литералов нет operator +. Обратите внимание, что строковый литерал не имеет тип string, но имеет тип const char *. Ваш второй пример будет работать, если вы его отредактируете следующим образом:

const string message = string("Hello") + ",world" + exclam;

Ответ 4

В случае 1 из-за порядка операций вы получаете:

(hello + ", world" ) + "!" который решает привет + "!" и, наконец, приветствовать

В случае 2, как отметил Джеймс, вы получаете:

( "Hello" + ", world" ) + exclam, который является конкат двумя строковыми литералами.

Надеюсь, что это ясно:)

Ответ 5

Разница между строкой (или, если быть точнее, std::string) и символьным литералом заключается в том, что для последнего не существует оператора +. Вот почему второй пример терпит неудачу.

В первом случае компилятор может найти подходящий operator+, причем первым аргументом является string, а второй - символьный литерал (const char*), поэтому он использовал это. Результатом этой операции снова является string, поэтому он повторяет тот же трюк, добавляя к нему "!".