Почему строковые литералы (char *) в C ++ должны быть константами? - PullRequest
44 голосов
/ 05 мая 2020

Недавно я изучал C ++ и понял, что строковые литералы в C ++ должны быть константами, а в C - нет. Вот пример. Следующий код будет действителен в C, но не в C ++:

char* str = "Hello World";

, чтобы сделать то же самое в C ++, необходимо использовать следующий оператор:

const char* str = "Hello World";

Кто-нибудь может объяснить почему?

Ответы [ 2 ]

38 голосов
/ 05 мая 2020

Немного расширяя ответ Кристиана Гиббонса ...

В C строковые литералы, такие как "Hello World", хранятся в массивах char, так что они видны в течение всего времени существования программы. . Строковые литералы предполагаются как неизменяемые, и некоторые реализации будут хранить их в сегменте памяти только для чтения (например, попытка изменить содержимое литерала вызовет ошибку времени выполнения). Некоторые реализации этого не делают, и попытка изменить содержимое литерала может не вызвать ошибку времени выполнения (может даже показаться, что она работает должным образом). Определение языка C оставляет поведение «undefined», чтобы компилятор мог обрабатывать ситуацию, как он считает нужным.

В C ++ строковые литералы хранятся в массивах <em>const</em> char, так что любые попытка изменить содержимое литерала вызовет диагностику c во время компиляции .

Как указывает Кристиан, ключевое слово const изначально не входило в состав C. Однако изначально он был частью C ++ и делает использование строковых литералов немного безопаснее.

Помните, что ключевое слово const не означает «сохранить это в постоянной памяти», а означает только «эта вещь не может быть целью назначения».

Также помните, что, если это не операнд операторов sizeof или унарных *, или строковый литерал, используемый для инициализации массива символов в объявлении, выражение типа «N-элементный массив T» будет преобразован («распад») в выражение типа «указатель на T», а значением выражения будет адрес первого элемента массива.

В C ++, когда вы пишете

const char *str = "Hello, world";

, адрес первого символа строки сохраняется в str. Вы можете установить str так, чтобы он указывал на другой строковый литерал:

str = "Goodbye cruel world";

, но то, что вы не можете сделать, - это изменить содержимое строки, что-то вроде

str[0] = 'h';

или

strcpy( str, "Something else" );
25 голосов
/ 05 мая 2020
В

C изначально не было ключевого слова const, поэтому устаревший код изменился бы, если бы они изменили литералы на требование const -квалификации после введения ключевого слова. Однако строковые литералы C неизменяемы, поэтому изменение содержимого является неопределенным поведением, даже если оно не соответствует требованиям const.

C ++, с другой стороны, был разработан с использованием const ключевое слово. Первоначально C ++ позволял присваивать строковые литералы не const -квалифицированным char * предположительно для совместимости с существующим кодом C. Однако, что касается стандарта C ++ 03, они решили отказаться от этой функциональности, вместо того, чтобы позволять диссонансу продолжаться вечно. Я предполагаю, что количество устаревшего кода C ++, полагающегося на не- const квалифицированные char * s, указывающие на строковые литералы, должно быть достаточно маленьким, чтобы это было достойным компромиссом.

...