Поэтому я перехожу с Java на C ++ и все еще не могу понять, как работают указатели>.< Надеюсь, что некоторые из вас, опытные программисты на C ++, могут мне помочь!
В классе мы создали реализацию стека и очереди, используя динамический массив.
Мой учитель использовал указатели для создания этих массивов в куче.
int* data = new int[25];
Чего я не понимаю, так это как вы можете вставить значения в массив с помощью «data [top]»? Я думал, что указатели просто держали адрес памяти? Я спрашиваю свою учительницу, как это работает, но я нахожусь в затруднительном положении, и она не сможет вернуться ко мне до завтрашнего дня>.<
Stack::push(int value) {
if(top==size) {
resize();
}
data[top] = value;
top++;
}
Я думал, что указатели просто держали адрес памяти?
Да, но вы можете делать что-то с этим адресом памяти. В частности, C ++ допускает нечто, называемое «арифметикой указателей», которое позволяет вам использовать адрес памяти для получения адреса другой памяти, расположенной относительно памяти, для которой у вас уже есть адрес. Например, если у вас есть адрес памяти, вы можете получить адрес памяти, расположенный сразу после него.
(квадраты — это ячейки памяти)
☐
☐
☐ ← I have the address of this memory in variable A
☐ ← I would like to get the address of this memory location and to store it in X
☐
☐
☐int *A = ...;
int *X = A + 1; // compute the address of the next memory location
Таким образом, массив — это ряд областей памяти. Для доступа к любому элементу массива вы просто берете адрес, который у вас есть, вычисляете адрес элемента, к которому хотите получить доступ, и затем используете этот новый адрес.
int *A = new int[10];
int *X = A + 5; // get the address of the memory five locations past where A points to
*X = 999;
Вам не нужно хранить адрес, который вы вычисляете, в переменной:
int *A = new int[10];
*(A+5) = 999;
C ++ обеспечивает сокращение для синтаксиса *(A+5)
, это оператор индекса массива:
int *A = new int[10];
A[5] = 999;
Одна вещь, которая интересна, — то, что оператор индекса массива действительно просто сокращение для этого *(A+5)
выражение. Так как вы можете перевернуть операнды и сделать *(5+A)
вы можете сделать то же самое с оператором индекса массива:
5[A] = 999;
Вы не должны этого делать, потому что это не очень читабельно.
Еще одна вещь, которую нужно знать об указателях: в Java есть указатели. Когда вы делаете
String s = new String();
на Яве s
это указатель Java просто пытается скрыть этот факт в то же время, что требует использования указателей в гораздо большей степени, чем в C ++. В Java нет арифметики с указателями, и вам не нужно вручную разыменовывать указатели в Java, как в C ++. Но учтите:
List<String> l = new List<String>();
List<String> m = l; // Do I have two lists, l and m, that can be modified independently? Or do I have two entities, l and m, that both refer to the same List object?
И помните те исключения Null Pointer, которые вы получаете в Java.
Если вы использовали Java, то вы уже использовали указатели. Они на самом деле не так уж отличаются в C ++, но они прямо видны и явны в C ++, а не плохо скрыты, как в Java.
Один из способов посмотреть на это data[top]
такой же как *(data + top)
, Итак, вы берете указатель data
добавить значение top
к нему (умноженному на размер целого), затем прочитайте или напишите это местоположение.
Увидеть: Указатели C ++ & Массивы
И вы правы, указатели хранят адреса только в тех точках памяти, где данные действительно находятся. Стек, который вы создаете, является просто классом, который обеспечивает определенный способ получения памяти и добавления памяти в массив.
Также проверьте: Стек C ++ STL
Это должно прояснить, как работают стеки.