Похожие презентации:
op2
1. Основы программирования на c/c++ Лекция 2: Типы, память. oopCpp@yandex.ru
12. Типы
Строго типизированный язык — это язык программирования, вкотором каждая переменная и выражение имеют определенный тип
данных или функций, который проверяется на этапе компиляции.
Основные характеристики:
Явная проверка типов — компилятор проверяет соответствие типов
перед выполнением операций.
Ограниченные неявные преобразования — автоматические
преобразования между типами минимальны или отсутствуют.
Предсказуемость — поведение программы более предсказуемо, так
как типы фиксированы.
В строго типизированных языках выражение "5" + 2 вызовет ошибку.
В слабо типизированных языках (JavaScript, PHP) это может дать
результат "52" (строковая конкатенация).
с/с++ - строго типизированный язык.
2
3. Типы
Тип называется встроенным, если компилятор знает, как представитьобъекты такого типа и какие операторы к нему можно применять (такие
как + и -) без уточнений в виде объявлений, которые создает
программист в исходном коде.
Типы, не относящиеся к встроенным, называют типами,
определенными пользователем. Они могут быть частью стандартной
библиотеки stl (например, классы string, vector и ofstream), или типами,
создаваемыми самим программистом.
3
4. Важность понимания типов и памяти
Язык C++ предоставляет программисту низкоуровневый контрольнад ресурсами, включая управление памятью.
Неправильное управление памятью неизбежно приводит к серьезным
проблемам:
Утечкам памяти (memory leaks) при неосвобожденных ресурсах
Неопределенному поведению (undefined behavior = UB) при
некорректных операциях
Критическим сбоям и уязвимостям в безопасности
Основополагающий принцип C++: "Не плати за то, что не
используешь"
4
5. Процесс компиляции и сегменты памяти
Трансляция программы проходит этапы:исходный код → компилятор → объектный код → линковщик →
исполняемый файл.
При запуске программа загружается в оперативную память, где организуется
несколько ключевых сегментов:
• Сегмент кода (Code) для инструкций программы
• Сегмент данных (Data) для глобальных переменных
• Стек (Stack) для вызовов функций и локальных переменных
• Куча (Heap) для динамического выделения памяти
5
6. Понятие типа данных
Тип данных представляет собой фундаментальное понятие, котороеопределяет:
• Размер занимаемой памяти, измеряемый в байтах
• Диапазон представляемых значений
• Набор допустимых операций над данными этого типа
6
7. Целочисленные типы
Целочисленные типы включают:• char (1 байт, может быть как signed, так и unsigned)
• short (2 байта), int (4 байта), long (4 или 8 байт), long long (8 байт)
• Все типы поддерживают модификаторы signed и unsigned
• Для гарантированного размера используются типы из <cstdint>: int32_t,
uint64_t
7
8. Типы с плавающей точкой
Типы с плавающей точкой обеспечивают работу с вещественными числами:• float (4 байта, приблизительно 7 значащих цифр)
• double (8 байт, приблизительно 15 значащих цифр) рекомендуется для
большинства вычислений
• long double (8 или 16 байт) для специализированных задач
8
9. Логический тип и void
Логический тип bool представляет два значения: true и false, занимаяобычно 1 байт.
Специальный тип void не имеет значений и используется:
• Как возвращаемый тип функций, которые не возвращают значение
• В качестве универсального указателя void* для работы с памятью
9
10. Оператор sizeof
Оператор sizeof позволяет определить размер типа или переменной вбайтах во время компиляции.
Например:
std::cout << sizeof(int); // Выведет 4 на большинстве современных платформ
std::cout << sizeof(double); // Выведет 8
Важно отметить, что sizeof(char) всегда гарантированно равен 1.
10
11. Ключевое слово auto
Ключевое слово auto позволяет компилятору автоматически вывести типпеременной на основе инициализатора.
Пример использования:
auto x = 42; // Компилятор определит тип int
auto y = 3.14; // Компилятор определит тип double
auto z = y; // Тип будет выведен как double
Несмотря на удобство, понимание системы типов остается обязательным.
11
12. Объявление и инициализация переменных
Определение переменной:int value; // создает неинициализированную переменную.
Инициализация:
int value = 10;
или современный синтаксис:
int value{10};
который предотвращает сужающие преобразования.
Настоятельно рекомендуется всегда инициализировать переменные при
объявлении.
12
13. Область видимости и время жизни
Глобальные переменные обладают глобальной областью видимости исуществуют в течение всей работы программы.
Локальные переменные видны только внутри блока
{}
где объявлены.
Время жизни локальных переменных ограничено временем выполнения
блока.
13
14. Пример области видимости
int global = 0; // Глобальная переменнаяvoid foo() {
int local = 42; // Локальная переменная в foo
// global - видна здесь
} // local уничтожается здесь
int main() {
foo();
// local - здесь не видна
}
14
15. Стек вызовов
Стек вызовов работает по принципу LIFO (последний пришел — первыйвышел).
При вызове функции в стек помещаются ее аргументы и локальные
переменные.
При возврате из функции эти данные автоматически удаляются из стека.
15
16. Память и адреса
Оперативная память представляется как массив байтов, каждый из которыхимеет уникальный адрес.
Адрес представляет собой числовое значение, обозначающее положение в
памяти.
Переменная является именованной областью памяти с определенным
типом.
16
17. Оператор взятия адреса (&)
Оператор взятия адреса (&)Оператор & возвращает адрес переменной в памяти.
Пример:
int x = 10;
std::cout << &x;
// Выведет адрес переменной x
17
18. Указатели
Указатель — это переменная, которая хранит адрес памяти другойпеременной.
Объявление:
int* p; // создает указатель на тип int.
Инициализация:
p = &x; // сохраняет адрес переменной x в указателе p.
18
19. Разыменование указателя (*)
Оператор * над указателем предоставляет доступ к значению посохраненному адресу.
Пример:
int x = 10;
int* p = &x;
std::cout << *p; // разыменование p. выведет 10
*p = 20;
// Изменяет значение x на 20
19
20. Нулевой указатель (nullptr)
Нулевой указатель не ссылается ни на какой объект.Современный C++ использует nullptr вместо устаревших NULL или 0.
Пример:
int* p = nullptr;
Попытка разыменования нулевого указателя приводит к неопределенному
поведению (UB).
20
21. Ссылки
Ссылка представляет собой псевдоним для уже существующейпеременной.
Объявление:
int& ref = x; // создает ссылку на переменную x.
Ссылка должна быть инициализирована при объявлении и не может быть
перенаправлена.
21
22. Сравнение указателей и ссылок
Указатель:• Может содержать значение nullptr
• Может быть перенаправлен на другой адрес
• Требует явного разыменования оператором *.
Ссылка:
• Всегда должна ссылаться на существующий объект
• Не может быть перенаправлена после инициализации
• Используется синтаксически как обычная переменная.
22
23. Передача по значению
При передаче по значению функция получает копию аргумента.Изменения внутри функции не влияют на оригинальную переменную.
Пример:
void func ( int x) { x = 100; }
int a = 5;
func(a);
// Значение a останется равным 5
23
24. Передача по указателю
При передаче по указателю функция получает адрес переменной.Изменения через указатель изменяет оригинальную переменную.
Пример:
void func (int* x) { *x = 100; }
int a = 5;
func ( &a ); // Значение a станет равным 100
24
25. Передача по ссылке
При передаче по ссылке функция работает непосредственно соригинальной переменной.
Изменения напрямую влияют на оригинал.
Пример:
void func (int& x) { x = 100; }
int a = 5;
func(a); // Значение a станет равным 100
Данный способ часто предпочтительнее для передачи параметров.
25
26. Стек vs Куча
Стек характеризуется:• Высокой скоростью выделения и освобождения памяти
• Автоматическим управлением памятью
• Ограниченным размером
Куча (динамическая память) характеризуется:
• Большим доступным размером
• Ручным управлением через new/delete
• Относительно медленной скоростью работы
26
27. Оператор new
Оператор new выделяет память в куче и возвращает указатель на ееначало.
Примеры:
int* p = new int;
// Неинициализированная память
int* p2 = new int(33); /* Память инициализирована значением 33 */
27
28. Оператор delete
Оператор delete освобождает память, ранее выделенную оператором new.Пример:
delete p;
Крайне важно освобождать всю выделенную память.
28
29. Динамические массивы
Выделение динамического массива:int* arr = new int [n]; // n – размер масссива.
Освобождение:
delete[ ] arr; // с обязательным использованием [ ].
Доступ к элементам:
arr[0], arr[1], и так далее.
29
30. Утечки памяти
Утечка памяти происходит когда память выделена (new), но не освобождена(delete).
Пример:
void leak() {
int* p = new int(100);
// забыли delete p;
}
// Указатель p уничтожается, но память остается занятой
30
31. Утечки памяти
Чтобы найти утечку памяти надо:В начале главного файла проекта разместить :
#define _CRTDBG_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>
// А в начале main() добавить следующую строку:
_CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
Тогда в окне Output покажется утечка.
Пример.
int* leak = new int[10]; // Пример утечки
В окне Output будет что-то вроде этого :
Dumping objects ->
{157} normal block at 0x000001F845F66630, 40 bytes long.
Data: <
> CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
31
Object dump complete.
32. Висячие указатели
Висячий указатель ссылается на уже освобожденную память.Пример:
int* p = new int(10);
delete p;
*p = 5; // Неопределенное поведение!
32
33. Указатели и const
Указатель на константу:const int* p = &x; // запрещает изменение *p.
Константный указатель:
int* const p = &x; // запрещает изменение p.
Комбинация:
const int* const p = &x; // запрещает оба изменения.
33
34. Ссылки и const
Константная ссылка:const int& ref = x; // не позволяет изменять значение через ссылку.
Особенно полезно для передачи больших объектов в функции без
копирования и с гарантией неизменности.
34
35. Константные параметры функций
Пример использования:void print( const std::string& str) {
std::cout << str;
// str[0] = 'X'; // Ошибка компиляции – попытка изменить значение
}
Данный подход обеспечивает эффективность и безопасность.
35
36. Составные типы данных: Структуры
Структура — это пользовательский тип данных, который позволяетобъединять переменные разных типов под одним именем.
Аналог "записи" или "объекта" в реальном мире (например, карточка
студента, книга в каталоге, меню в кафе).
struct Student {
int id;
// ID номер
char name [256]; // ФИО – здесь не более 255 символов
int course;
// Курс
double grade; // Средний балл
};
36
37. Использование
// При созданииStudent student1 = {12345, "Иванов Иван", 2, 4.8};
// Или позже, обращаясь к полям
Student student2;
student2.id = 54321;
// student2.name = "Петрова Мария"; // будет ошибка – так нельзя
strcpy(student2.name, "Петрова Мария");
student2.course = 1;
student2.grade = 5.0;
37
38. Доступ к полям структуры
Через оператор точку (.) — если работаем с самой структурой.student1.id = // Новый id ;
cout << student1.id;
Через оператор стрелку (->) — если работаем с указателем на структуру.
Student* ptr = &student1;
ptr->course = 3; // Эквивалентно (*ptr).course = 3;
38
39. Передача структур в функции
• По значению: Создается копия всей структуры. Изменения внутри функциине затрагивают оригинал.
void printStudent( Student s);
• По ссылке: Передается сам оригинал. Изменения внутри функции меняют
переданную структуру. Эффективно по памяти.
void initStudent ( Student& s);
• По константной ссылке: Передается оригинал, но защищен от изменений.
Идеально для передачи больших структур только для чтения.
void printStudent( const Student& s);
39
40. Итоги
• Типы данных определяют размер памяти, представление и допустимыеоперации
• Память организуется в стек (автоматическое управление) и кучу (ручное
или умное управление)
• Указатели и ссылки предоставляют различные механизмы работы с
памятью
• Константность (const) обеспечивает безопасность и выразительность кода
• Структуры помогают организовать код, делая его более читаемым и
отражающим предметную область.
40
41. ДЗ 2. Создаем проект 6 – pr6
Дан некоторый неполный код. Надо его дополнить в соответствии скомментариями.
#include <iostream>
int main() {
int a = 10;
int *p = &a;
double b = 5.5;
double *q = &b;
std::cout << "p: " << p << std::endl;
// добавляем к р 1 и снова распечатываем (p+1)
// то же самое для переменной q
// затем распечатать ++p
// при помощи оператора new выделить память и не освобождать ее для
// проверки на утечку памяти – добавить в код нужное для такой проверки.
// распечатать также имя, фамилию, группу и дату рождения
return 0;
}
Кратко прокомментировать каждую операцию. Объяснить результаты.
41
42. Контрольная работа 2
На листе бумаги напишите свою фамилию, имя и группу.Задание.
Напишите функцию
void swap (int *a, int *b)
которая меняет значения переменных a и b местами, используя
указатели.
В функции main задайте два числа, выведите их на консоль, затем
передайте их в swap и вновь выведите их на консоль.
42
Программирование