В качестве фона я недавно дал ответ на этот пост:
И он непреднамеренно начал очень длинную цепочку комментариев о указателях против массивов в С++, потому что я пытался упростить, и я сделал выражение "массивы - указатели". Хотя мой окончательный ответ звучит довольно прилично, это было только после некоторого тяжелого редактирования в ответ на многие комментарии, которые я получил.
Этот вопрос не предназначен для приманки троллей, я понимаю, что указатель и массив - это не одно и то же, но некоторые из доступных синтаксисов на языке С++, безусловно, заставляют их вести себя очень одинаково во многих случаях. (FYI, мой компилятор i686-apple-darwin9-g++-4.0.1
on OS X 10.5.8
)
Например, этот код компилируется и работает отлично для меня (я понимаю, что x[8]
является потенциальной ошибкой сегментации):
//this is just a simple pointer
int *x = new int;
cout << x << " " << (*x) << " " << x[8] << endl; //might segfault
//this is a dynamic array
int* y = new int[10];
cout << y << " " << (*y) << " " << y[8] << endl;
//this is a static array
int z[10];
cout << z << " " << (*z) << " " << z[8] << endl;
Этот фрагмент делает его похожим на то, что указатели и массивы могут использоваться почти одинаково, но если я добавлю это в нижнюю часть этого кода, последние две строки не будут компилироваться:
x = y;
x = z;
y = x;
y = z;
//z = x; //won't compile
//z = y; //won't compile
Таким образом, компилятор, по крайней мере, понимает, что z
и x
- это разные вещи, но я могу отлично обменивать x
и y
.
Это еще больше запутывает, когда вы смотрите на передачу массивов на функции и возврат массивов из функций. Рассмотрим этот пример (опять же, я знаю о потенциальных ошибках сегментации при передаче x
):
void foo(int in[])
{
cout << in[8] << endl;
}
void bar(int* in)
{
cout << in[8] << endl;
}
int main()
{
//this is just a simple pointer
int *x = new int;
foo(x);
bar(x);
//this is a dynamic array
int* y = new int[10];
foo(y);
bar(y);
//this is a static array
int z[10];
foo(z);
bar(z);
}
Весь этот код правильно компилируется и запускается на моей машине.
Я чувствую, что у меня есть достойное внутреннее понимание того, что происходит здесь, но если вы попросили меня четко сформулировать, что происходит, я не чувствую, что могу удовлетворительно объяснить. Итак, вот что я получаю:
-
Когда я передаю массив функции
int* in
вместоint in[]
, что я получаю или теряю? То же самое верно при возврате массива какint*
? Есть ли когда-либо плохие побочные эффекты от этого? -
Если бы я спросил вас, что такое тип данных
y
, вы бы указали на int, массив ints или что-то еще? -
Аналогично, что происходит, когда я говорю
x = y
vs.x = z
? Я все еще могу использоватьx[]
и получить доступ к вещам, которые изначально были вy
илиz
, но действительно ли это потому, что арифметика указателя приводит меня в пространство памяти, которое остается в силе?
Я вырыл все похожие вопросы с массивами/указателями на SO, и мне трудно найти окончательное объяснение, которое очищает это для меня раз и навсегда.