Перейти к содержанию
СофтФорум - всё о компьютерах и не только

С++: Указатели


Рекомендуемые сообщения

Указатель - это объект, в котором хранится адрес чего-то. У этого объекта есть некоторые свойства, например, он помнит размер блока памяти, адрес которого он хранит. Он знает и другие вещи, например, можно ли изменять содержимое блока памяти, на который он ссылается. Указатель часто используется для работы с массивами, так как к содержимому указателя надо прибавить смещение, чтобы получить адрес нужного элемента массива. Но очень полезен, как посредник, и для работы с другими объектами.

Пример использования указателя для работы с динамическим массивом:

Создаем указатель на блок памяти, предназначенный для хранения целого, выделяем память для хранения 50-ти целых и помещаем адрес начала этого блока памяти в указатель:

int *p; p=new int[50];

Теперь с этим массивом можно работать:

p[2]=8;

или, что то же самое,

*(p+2)=8

(тут мы прибавили к указателю два размера блоков памяти, соответствующих типу указателя, взяли ячейку с этим адресом (операция *) и поместили нее 8 ).

Когда этот массив больше не нужен, память можно освободить:

delete [] p;

Можно создавать и массивы указателей, в том числе динамические, и т.д.

Ссылка на комментарий
Поделиться на другие сайты

Кстати, об указателях, а точнее о массивах в С++ Знаю один прикол, не имеющий, правда практического прменения... К ячейке массива мы обращаемся обычно как например p[10]==3 Если написать 10[p]==3 то это тоже будет работать! Связано это то ли с предпроцессором С++ то ли с компиляцией, написание p[10] преобразуется в форму p+10, и поэтому 10[p] будет выглядеть как 10+p то есть тоже верно...

Ссылка на комментарий
Поделиться на другие сайты

Маленькие дополнения.

1. При использовании указателей снимается ограничении на размер массива.

Можно задать массив хоть из 10 млрд. элементов. Обычным способом так сделать нельзя.

2. Обращение по адресу работает быстрее, чем просто обращение к элементу массива.

Ссылка на комментарий
Поделиться на другие сайты

Тебе Тролль все прекрасно написал...

Создаем указатель на блок памяти, предназначенный для хранения целого, выделяем память для хранения 50-ти целых и помещаем адрес начала этого блока памяти в указатель: int *p; p=new int[50];

На тебе прмерный кусок программы:

int size=0;

cout << "Enter size of array: ";

cin >> size;

int *p = new int;

for (int i=0;i<size;i++)

{

p=i+1;

cout << p << ' ';

}

delete [] p;

Ссылка на комментарий
Поделиться на другие сайты

Огромное спасибо. Наверное, это книжка тупая попалась...

Да, мало хороших книг :blink: Вот человек - хорошая книга ;) А форум - целая библиотека хороших книг :D

Ссылка на комментарий
Поделиться на другие сайты

Smagl

Ну да, а есть ведь ещё чаты, аськи и т.п. Так что интернетом можно назвать бесконечное множество книг

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...
А как создать массив с размерами, которые задаёт юзер?

Для этого существуют структуры данных, именуемые связанными списками.

Ссылка на комментарий
Поделиться на другие сайты

Alex1010

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

Можно моделировать массив связанным списком или связанный список массивом, но в любом из этих случае это будет очень нерационально.

Ссылка на комментарий
Поделиться на другие сайты

Alex1010

Сошлюсь на программу, которую написал Ray и поместил в этой же теме несколькими сообщениями выше, она прекрасно показывает создание такого массива на работающем примере.

Ссылка на комментарий
Поделиться на другие сайты

  • 5 лет спустя...

Возник вопрос касательно указателя и выделения памяти динамически:

Известно, что в результате неправильного манипулирования паматью можно получить ее утечку. К примеру:

int *p = new int;*p=10;p=new int;*p=15;

В чем проблема приведенного кода ?

В строке 1 выделяется память для значения int. В строке два, в эту область записывается значение 10.

Далее указателю присваивается адрес другой области, в которую записывается число 15.

Таким образом, первый участок памяти с числом 10, оказался недоступен. И нельзя ни использовать ни освободить его... Пример взят из Либерти...

Идя дальше по книге, наткнулся на такую программу.

class Mammal{   public:   Mammal():itsAge(1) {cout << "Mammal constructor...\n";}   virtual  ~Mammal() {cout << "Mammal destructor...\n";}   virtual void Speak () const {cout << "Mammal speak!\n";}  protected:   int itsAge;};class Dog: public Mammal{ public:  void Speak()const {cout << "Woof!\n";}};class Cat: public Mammal{    public: 	  void Speak()const {cout << "Meow!\n";}};class Horse: public Mammal{public: 			void Speak() const {cout << "Winnie!\n";}};int main(){Mammal *theArray[3];Mammal *ptr;int choice, i;for(i=0; i<3; i++) {	cout << "(1)dog  (2)cat  (3)horse: ";	cin >> choice;	switch(choice)	{	case 1: ptr = new Dog; break;	case 2: ptr = new Cat; break;	case 3: ptr = new Horse; break;	} theArray[i] = ptr;}for(i=0; i<3; i++)	theArray[i]->Speak();return 0;}

Если заглянуть в функцию main, в первый цикл, в тело оператора switch, то разве там нельзя наблюдать упомянутую в предыдущем примере

утечку ? Цикл содержит 3 итерации, в каждой из которых указателю ptr присваивается адрес новой области, без предварительного освобождения...

Или автор делает скидку на скорое завершение программы, т.к. при этом память освободиться автоматически ?

Ссылка на комментарий
Поделиться на другие сайты

Архимаг:

for(i=0; i<3; i++) {

cout << "(1)dog (2)cat (3)horse: ";

cin >> choice;

switch(choice)

{

case 1: ptr = new Dog; break;

case 2: ptr = new Cat; break;

case 3: ptr = new Horse; break;

} theArray = ptr;

}

ptr действительно присваивается каждый раз адрес новой области, но он тут же передается в theArray = ptr;

Все эти области нужны, они становятся содержанием массива theArray, поэтому отдавать обратно отведенную для них память нельзя, ptr тут - просто необязательное передаточное звено для адреса.

Ссылка на комментарий
Поделиться на другие сайты

Архимаг:

ptr действительно присваивается каждый раз адрес новой области, но он тут же передается в theArray = ptr;

Все эти области нужны, они становятся содержанием массива theArray, поэтому отдавать обратно отведенную для них память нельзя, ptr тут - просто необязательное передаточное звено для адреса.

Т.е. если взять два указателя:

int *p1 = new int;

int *p2 = p1;

Они будут содержать адрес одной и той же области. Если освободить указатель p1: delete p1; то работа с указателем p2 будет невозможно ?

Ссылка на комментарий
Поделиться на другие сайты

Присвоить ему новый адрес можно. А по старому адресу, на который он ссылается, может уже лежать все, что угодно. Фактически мы освобождаем для любых других применений не указатель p1, а область памяти, на которую он указывал. Адрес в указателе p2 остается прежним, но в квартире по указанному адресу могут быть уже другие жильцы, чаще всего ноли, но это зависит от компилятора.

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...