Не удается преобразовать из ' int * 'в 'int []'?
Я знаю, что это может быть общий вопрос, но я пытался искать, но все еще не могу найти четкого ответа.
у меня есть следующий код:
int* f() {
int a[] = {1,2,3};
return a;
}
int main() {
int a[] = f(); // Error here
getch();
return 0;
}
этот код выдает сообщение об ошибке:"Cannot convert from 'int *' to 'int []'"
Я нашел это довольно странным, потому что я прочитал, что указатель и массив похожи. Например, мы можем использовать[i] вместо *(a + i). Кто-нибудь может дать мне ясное объяснение, пожалуйста?
4 ответов
на самом деле в этом коде есть две ошибки.
во-первых, вы возвращаете адрес временного (массив int внутри f), поэтому его содержимое не определено после завершения функции. Любая попытка доступа к памяти, на которую указывает возвращаемый указатель, вызовет неопределенное поведение.
во-вторых, в C++нет неявного преобразования указателей в типы массивов. Они похожи, но не идентичны. Массивы могут распадаться на указатели, но это не работает наоборот, поскольку информация теряется по пути-указатель просто представляет адрес памяти, а массив представляет адрес непрерывной области, как правило, с определенным размером. Также вы не можете назначить массивам.
например, мы можем использовать[i] вместо *(a + i)
это, однако, имеет мало общего с различиями между массивами и указателями, это просто синтаксическое правило для типов указателей. Поскольку массивы распадаются на указатели, он работает для массивов, а также.
тип int[] фактически не существует.
когда вы определяете и инициализируете массив как
int a[] = {1,2,3};
компилятор подсчитывает элементы в инициализаторе и создает блок нужного размера; в этом случае он становится волшебным образом:
int a[3] = {1,2,3};
int[] используется в качестве параметра функции, вместо этого, это просто int *, т. е. указатель на первый элемент массива. Никакой другой информации с ним не ведется, в частности ничего сохранила размер. То же самое происходит, когда вы возвращаете указатель
обратите внимание, что массив не указатель: указатель можно изменить, чтобы указать на другие вещи, в то время как массив всегда ссылается на ту же память; указатель ничего не знает о том, насколько велико пространство памяти, на которое он указывает, в то время как размер массива всегда известен во время компиляции. Путаница возникает из-за того, что массив распады к указателю на его первый элемент во многих случаях и передача его функции/возврат его из функции являются некоторыми из этих обстоятельств.
Итак, почему ваш код не работает? Есть две большие ошибки:
вы пытаетесь инициализировать массив с указателем. Мы сказали, что
int *не несет никакой информации о в размере массива. Это просто указатель на первый элемент. Поэтому компилятор не может знать, насколько большойaдолжно быть сделано для разместить вещи, возвращенныеf().-
на
fвы возвращаете указатель на переменную, которая является локальной для этой функции. Это неправильно, потому что указатель не хранит данные, он только точки туда, где хранятся данные, т. е. в вашем случае вaместные кf. Потому что этот массив местные функции, он перестает существовать, когда функция завершает работу (т. е. вreturn).это означает, что вы возвращаете указатель указывает на вещи, которые больше не существуют; рассмотрим код:
int * a = f();инициализация работает, и вы можете попробовать использовать
aдалее в функции, ноaбудет указывать на больше не существующий массивf; в лучшем случае ваша программа рухнет (и вы сразу заметите, что вы сделали что-то не так), в худшем это будет работать в течение некоторого времени, а затем начать дает странные результаты.
int * и int [] похожи, но разные. int * является реальным указателем, между тем int[] является ссылкой на массив ( своего рода "постоянным указателем" на начало данных), который не может быть изменен. Таким образом, int * может быть threated как int [], но не viceversa.
можно использовать a[b] и*(a+b) взаимозаменяемо, потому что именно так a[b] определяется, когда один из a или b является указателем, а другой-целочисленным или перечислительным типом.
Примечание: это также означает, что такие выражения, как 42[a] совершенно законно. Читатели-люди могут сильно возражать, но компилятор и глазом не моргнет.