пара простых вопросов о базовом использовании указателя в c ++ и модели памяти c ++ - PullRequest
0 голосов
/ 31 августа 2011

Я учился вместе со Стэнфордскими курсами по iTunes U и попал в курсоры по C ++. Я думаю, что понимаю, как работают указатели, но я просто хочу проверить, как сделать некоторые простые вещи. Допустим, я хочу создать динамический массив:

    double *array;

На данный момент в стеке есть переменная с именем «массив», а в куче ничего нет. Первый вопрос - что хранится в «массиве» на данный момент? Указатель на какой-то бессмысленный кусок памяти?

Затем я выделяю память, используя «new»:

    array = new double[10];

Второй вопрос - на данный момент, что хранится в «массиве»? Указатель на какой-то непрерывный фрагмент памяти, достаточно большой, чтобы вместить десять двойников? (Извините за простые вопросы, но я действительно хочу убедиться, что я понимаю)

Я присваиваю double 2.0 каждому элементу в массиве:

    for(int i=0; i<array.length(); i++) array[i]=2.0;

Третий вопрос - отличается ли это от использования оператора разыменования для присваивания? (т.е. *array[i]=2.0). Затем я передаю массив другой функции:

    myFunc(double array[]){
        for(int i=1; i<array.length(); i++){
            array[i]=array[i]*array[i-1];
        }
    }

Четвертый вопрос - при переходе к myFunc, так как массив - это массив указателей на двойники, а не массив двойных, он передается по ссылке без "&", верно? Это означает, что операции в моем цикле влияют на фактические данные, хранящиеся в «массиве». Что если бы я хотел передать по значению, чтобы не касаться данных в «массиве»? Буду ли я использовать

    myFunc(double *array[]){...}?

Последний вопрос - что если я по какой-то причине хотел манипулировать адресами памяти для содержимого «массива»? Могу ли я использовать

    someVar = &array[5];

назначить шестнадцатеричный адрес массива [5] для someVar?

Я читал раздел об указателях в ридере и смотрел видео Бинки с дюжиной раз, и оно все еще не имеет смысла. Любая помощь будет принята с благодарностью.

РЕДАКТИРОВАТЬ: Большое спасибо всем, кто до сих пор ответил. Если вы не возражаете, у меня есть еще один вопрос. В объявлении double *array; «массив» объявляется как указатель на двойное число, но как только я использую «новое» для его присвоения, «массив» перестает быть указателем на двойное и становится массивом двойных, верно?

Ответы [ 3 ]

4 голосов
/ 31 августа 2011
  1. array содержит ненужные данные - все, что было в этой ячейке памяти до существования array, все еще там.Если вы попытаетесь поиграть с ним, вы будете стрелять себе в ногу, поэтому вам нужно назначить его в действительное место в памяти (отсюда последующий вызов new[]).
  2. Да, array теперь содержит указатель (адрес памяти) на некоторый непрерывный фрагмент памяти, достаточно большой, чтобы вместить десять двойных.
  3. *array[i]=2.0 фактически не скомпилируется.массив [i] приводит к double, и вы не можете использовать оператор разыменования для double.
  4. То, что вы передаете, - это адрес первого элемента в массиве.Таким образом, вы передаете указатель по значению, а массив - по ссылке (так как указатель является ссылкой на массив.) Чтобы передать сам массив по значению, вам потребуется один параметр для каждой записи.Вы также можете скопировать массив и отправить копию, но сама копия также будет передана по ссылке.
  5. double* someVar = &array[5]; вернет вам указатель на элемент 6 th массива.array[5] дает вам двойное значение, и взятие его адреса (с &) даст вам адрес памяти (указатель) этого двойного числа.
2 голосов
/ 31 августа 2011
  1. Да, это то, что происходит
  2. Определенно. Более конкретно, указатель на начало непрерывного фрагмента памяти.
  3. Не в этом случае; * (для разыменования) - унарный оператор, и все же вы передали ему два аргумента. Вы можете быть уверены, что выполняется умножение (или перегруженная версия), а также, что может означать array[i](*array[i-1])? вы не можете разыменовать что-то, что не является указателем (или не перегружен унарный оператор *)
  4. Вы передаете указатель только по значению, а не по данным. Если вы хотите передать данные по значению (сделать их неизменными вне функции), вам нужно сначала скопировать их и передать (или просто использовать vector)
  5. Да, вы просто получаете адрес части непрерывной памяти, и вы можете сохранить адрес и изменить разыменованное значение в другом месте, массив будет также изменен.

Кроме того, будьте утомлены тем, что когда вы выделяете кучу, вы должны впоследствии удалить память. В этом случае вы бы использовали delete[] array;

1 голос
/ 31 августа 2011

После объявления переменная array содержит произвольное значение.Вам не разрешено ничего делать с этим значением.После new он содержит указатель на непрерывный диапазон памяти, достаточно большой, чтобы вместить 10 двойных.*array[i]=2.0 является ошибкой (это означает, что массив является массивом указателей на удвоение).Оператор индексирования [] - это просто синтаксический сахар для *(array+i)=2.0.

Четвертый вопрос: СКАЖИТЕ ЧТО ??У вас нет массива указателей на двойники где-либо в этом коде.В функциях void f(double *x) и void f(double x[]) - ОДНА И ТО ЖЕ вещь: указатель на double.Если вы передадите f массив, x получит адрес первого элемента (который является ЗНАЧЕНИЕМ массива).

Вы не можете передавать массивы по значению.Кроме того, они всегда передаются по значению (как и все остальное в C), но обратите внимание, что VALUE массива является адресом его первого элемента.

Ваш последний вопрос: я понятия не имею, что выпытаюсь добиться, но вопрос ясно показывает, что ты запутался.Адрес - это адрес, такого понятия как «шестнадцатеричный адрес» не существует.

...