Menu
Coddy logo textTech

Указатели и ссылки

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy — урок 13 из 104.

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

Указатель хранит адрес памяти другой переменной. Вы объявляете его с помощью * и получаете адрес, используя &.

int value = 42;
int* ptr = &value;    // ptr хранит адрес value

std::cout << ptr;     // Выводит адрес памяти
std::cout << *ptr;    // Разыменование: выводит 42

Ссылка — это псевдоним для существующей переменной. После привязки она всегда ссылается на эту переменную. Она объявляется с помощью &.

int value = 42;
int& ref = value;     // ref — это псевдоним для value

ref = 100;            // Изменяет value на 100
std::cout << value;   // Выводит 100

Ключевые различия:

УказателиСсылки
Могут принимать значение nullДолжны быть инициализированы
Могут быть переназначеныНе могут быть перепривязаны
Используйте * для доступа к значениюДоступ к значению напрямую
Могут ни на что не указыватьВсегда валидны

Оба механизма важны для эффективной передачи объектов в функции без копирования и для работы с памятью, выделенной в куче. Ссылки безопаснее и проще, в то время как указатели обеспечивают большую гибкость, когда требуется переназначение или проверка на null.

challenge icon

Задание

Легко

Давайте создадим простую систему манипулирования значениями, которая демонстрирует, как по-разному работают указатели и ссылки при изменении данных.

Вы создадите два файла для организации вашего кода:

  • ValueOps.h: Определите три функции, которые изменяют целые значения различными способами:
    • doubleByPointer(int* ptr) — принимает указатель и удваивает значение, на которое он указывает
    • tripleByReference(int& ref) — принимает ссылку и утраивает значение
    • swapValues(int* a, int* b) — принимает два указателя и меняет местами значения, на которые они указывают
  • main.cpp: Считайте два целых числа из входных данных, затем продемонстрируйте работу как указателей, так и ссылок:
    • Выведите исходные значения: "Original: <first> <second>"
    • Используйте doubleByPointer для первого значения, затем выведите: "After double: <first>"
    • Используйте tripleByReference для второго значения, затем выведите: "After triple: <second>"
    • Используйте swapValues, чтобы поменять значения местами, затем выведите: "After swap: <first> <second>"

При вызове функций с указателями не забудьте использовать оператор взятия адреса (&), чтобы передать адрес переменной. Ссылки работают более естественно — просто передавайте саму переменную напрямую.

Подключите ваш заголовочный файл в main.cpp с помощью #include "ValueOps.h".

Шпаргалка

Указатель хранит адрес памяти другой переменной. Объявите его с помощью * и получите адрес, используя &:

int value = 42;
int* ptr = &value;    // ptr хранит адрес value

std::cout << ptr;     // Выводит адрес памяти
std::cout << *ptr;    // Разыменование: выводит 42

Ссылка — это псевдоним для существующей переменной. Объявите ее с помощью &:

int value = 42;
int& ref = value;     // ref — это псевдоним для value

ref = 100;            // Изменяет value на 100
std::cout << value;   // Выводит 100

Ключевые различия:

УказателиСсылки
Могут быть нулевыми (null)Должны быть инициализированы
Могут быть переназначеныНе могут быть перепривязаны
Используйте * для доступа к значениюДоступ к значению напрямую
Могут указывать в никудаВсегда валидны

При вызове функций с указателями используйте оператор взятия адреса (&), чтобы передать адрес переменной. Ссылки работают напрямую — просто передайте переменную.

Попробуйте сами

#include <iostream>
#include "ValueOps.h"
using namespace std;

int main() {
    // Считать два целых числа из входных данных
    int first, second;
    cin >> first;
    cin >> second;
    
    // Вывести исходные значения
    cout << "Original: " << first << " " << second << endl;
    
    // TODO: Используйте doubleByPointer для первого значения (передайте адрес с помощью &)
    
    // TODO: Вывести после удвоения
    
    // TODO: Используйте tripleByReference для второго значения (передайте переменную напрямую)
    
    // TODO: Вывести после утроения
    
    // TODO: Используйте swapValues, чтобы поменять значения местами (передайте адреса с помощью &)
    
    // TODO: Вывести после обмена значениями
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование