2015-05-13 4 views
0

я не понимаю, как указатель может присвоить массив символов или строку как:инициализировать указатель на массив символов

char* Carr = new char[5]; 
Carr = "Hello"; 

однако это ниже код не работает:

int* Iarr = new int[5]; 
Iarr = { 1,2,3,4 }; 

Я знаю, что указатель может присвоить ссылку не значение, так как компилятор принимает строку?

ответ

5

Первый не присваивает массив. Он меняет указатель, так что он указывает на статический массив, определенный строковым литералом, а не на динамический массив, который вы выделили. Теперь динамический массив просочился, и у него нет доступа к нему. В современном C++ это не должно компилироваться, поскольку литерал является постоянным, поэтому только const char * может указать на него.

Второй не работает, потому что, в отличие от строкового литерала, скошенный список не создает массив или что-то еще, что вы можете назначить указателю.

Если вы хотите назначить массив, используйте std::array, std::string или std::vector.

1

При использовании

Carr = "Hello"; 

после выделения char указателя с помощью new, вы теряете ссылку на выделенную память (приводящей к памяти утечке) и вы делаете Carr точку в строку буквального "Hello".

Здесь

Iarr = { 1,2,3,4 }; 

вы назначили int* в список инициализации (который не имеет никакого смысла). Вот почему компилятор жалуется, когда вы пытаетесь это сделать.

+0

Он не присваивает 'int *' 'int'. Он присваивает 'int *' списку инициализации ints, что делает примерно такое же значение, как назначение символа 'char *' в строковый литерал. Только компилятор не обрабатывает списки инициализации так же, как строковые литералы, вполне разумно ожидать, что это произойдет. –

+0

Я вижу. Отредактировал ответ. –

1

Строковые литералы (т. Е. Последовательности символов, заключенные в двойные кавычки) являются особым случаем. Компилятор C++ имеет специальный код, который помещает их содержимое в определенную область внутри кода и передает вашу программу указателю на него. Строковые литералы также совместимы с указателями символов const, поэтому вы можете сделать задание (вы должны получить предупреждение или ошибку, потому что ваш Carr не const).

Нет такой обработки массивов целых чисел. Хотя вы можете предоставить им инициализаторы, вы не можете создавать их совокупности так же, как вы делаете «совокупности символов», помещая их в двойные кавычки: компилятор не поддерживает ее.

К счастью, большую часть времени вам не нужно делать, потому что стандартная библиотека C++ обеспечивает превосходные альтернативы для массивов и строк. Например, вы можете переписать Iarr инициализации, как это:

auto Iarr = vector<int> {1, 2, 3, 4, 5}; 
0

Ни первый, ни второй фрагмент кода действует в C++ (после 2011 года).

Перед C++ 11 стандарта C++ поддерживается, но имел, как устаревшего после первого стандарта C++ в 1998 году, неявное преобразование строки буквальной на указатель непредставленного const элемента, получая указатель на первый символ.

Так как это довольно опасно, он был удален.


Исправленный вариант первого примера:

char const* Carr = new char[5]; 
Carr = "Hello"; 

Здесь присваивание Carr не присваивает массив, а указатель на первый элемент массива.

Он вызывает неявное преобразование из массива в указатель на первый элемент, называемый распад. Существует соответствующий распад (неявное преобразование) для функции для функции указателя.


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

Смежные вопросы