Что такое указатель?
Это переменная, хранящая адрес другой переменной.
Статическая память
Статическая память предназначена для хранения глобальных и статических переменных.
Переменные объявляются единожды и существуют до завершения программы.
Динамическая память
Программа запрашивает память в процессе выполнения.
Память освобождается вручную, когда она больше не нужна.
Динамическая память позволяет создавать массивы переменной длины.
Пример динамического выделения:
cpp
int* arr = new int[10]; // Выделяем память для массива из 10 элементов
delete[] arr; // Освобождаем выделенную память
Указатели
Определение и основные операции
Указатель — переменная, содержащая адрес другой переменной.
Операции:
& — получение адреса переменной.
* — разыменование указателя (доступ к значению по адресу).
Пример использования:
cpp
int x = 10; // Объявляем переменную x и инициализируем её значением 10
int* px = &x; // Указатель px получает адрес переменной x
*px = 20; // Разыменовываем указатель px и присваиваем x новое значение 20
& — узнаёшь адрес переменной (где находится эта фигня).
* — идёшь по адресу и работаешь с тем, что там лежит.
Особенности
Указатель может указывать только на адрес.
Разыменование *px позволяет читать и изменять значение переменной, на которую указывает указатель.
Пример:
int y = *px + 1; // Читаем значение x через указатель px, добавляем 1 и записываем в y
Инициализация и работа
Пример программы, демонстрирующей основные операции:
cpp
#include <iostream> // Подключаем библиотеку для ввода-вывода
using namespace std; // Используем пространство имен std
int main() {
int x = 10; // Объявляем переменную x
int y = 5; // Объявляем переменную y
int* px = &x; // Указатель px получает адрес переменной x
int* py = &y; // Указатель py получает адрес переменной y
cout << "Адрес x: " << px << endl; // Выводим адрес переменной x
cout << "Значение x: " << *px << endl; // Выводим значение x через разыменование px
*px = 99; // Изменяем значение переменной x через указатель px
cout << "Новое значение x: " << x << endl; // Выводим обновленное значение x
py = px; // Присваиваем указателю py значение px, теперь py указывает на x
cout << "Значение через py: " << *py << endl; // Выводим значение x через указатель py
return 0; // Завершаем выполнение программы
}
Указатели и массивы
Имя массива — указатель на его первый элемент.
Индексация массива эквивалентна работе с указателями.
Пример:
cpp
int arr[5] = {1, 2, 3, 4, 5}; // Создаем массив из 5 элементов
int* ptr = arr; // Указатель ptr получает адрес первого элемента массива
cout << *ptr << endl; // Разыменовываем ptr и выводим значение arr[0]
cout << *(ptr + 1) << endl; // Разыменовываем ptr + 1 и выводим значение arr[1]
Арифметика указателей
ptr + i — указатель на элемент i.
*(ptr + i) — значение элемента массива.
Пример вывода массива через указатель:
cpp
for (int i = 0; i < 5; i++) { // Проходим по массиву
cout << *(ptr + i) << " "; // Выводим каждый элемент через разыменование указателя
}
Указатели как аргументы функций
Указатели позволяют передавать аргументы по ссылке.
Это позволяет изменять значения переменных из вызывающей функции.
Пример функции обмена значений:
cpp
void Swap(int* a, int* b) { // Функция принимает два указателя на переменные
int temp = *a; // Сохраняем значение переменной a через разыменование
*a = *b; // Присваиваем a значение b через разыменование
*b = temp; // Присваиваем b сохраненное значение a
}
int main() {
int x = 10, y = 20; // Объявляем две переменные
Swap(&x, &y); // Передаем адреса переменных x и y в функцию Swap
cout << x << " " << y << endl; // Выводим измененные значения x и y (20 10)
return 0; // Завершаем выполнение программы
}
NULL и nullptr
Опасность неинициализированных указателей
Указатель без инициализации содержит случайное значение.
Попытка разыменования приведет к ошибке.
Нулевые указатели
Используются для обозначения, что указатель никуда не указывает.
Современный способ — nullptr.
Пример:
cpp
int* ptr = nullptr; // Инициализируем указатель как нулевой
if (ptr == nullptr) { // Проверяем, указывает ли указатель куда-либо
cout << "Указатель пустой" << endl; // Выводим сообщение, если указатель пустой
}
Сравнение способов
0 — старый стиль.
NULL — макрос из C.
nullptr — предпочтительный вариант в C++.
Пример использования:
cpp
int* ptr = nullptr; // Используем nullptr для инициализации указателя
if (ptr == nullptr) { // Проверяем, что указатель нулевой
cout << "Null pointer" << endl; // Выводим сообщение о нулевом указателе
}