Основные преимущества языков низкого уровня
Основной недостаток языков низкого уровня – сложность программирования из-за огромных размеров исходного кода
Главное преимущество языков высокого уровня – быстрота разработки сложных программных продуктов
Основные недостатки языков высокого уровня
Основные этапы разработки программы
Этапы создания исполняемого файла (.exe)
Литералы
Логический литерал
Типы данных
Целочисленные типы
Целочисленные типы
Целочисленные типы
Символьные типы
Вещественные типы
Логический тип
Правила именования идентификаторов:
В зависимости от количества операндов операторы бывают:
Арифметические операторы
Арифметические операторы
Сокращённые формы операторов: += -= *= /= %=
Сужающие преобразования бывают:
Операторы отношения
Логические операторы
Логическое «ИЛИ»
Логическое «И»
Логическое «НЕ»
Оператор ветвления «if»
Оператор ветвления «if»
Оператор ветвления «if»
Виды циклов
Цикл с предусловием while
Цикл с постусловием do while
Параметрический цикл for
Объявление массива
Инициализация массива
Количество элементов массива можно не указывать. Размер массива определяется исходя из числа элементов в списке инициализации.
Если значений в списке инициализации меньше чем количество элементов массива, то оставшиеся значения автоматически заполняются
Если значений в списке инициализации больше чем количество элементов массива, то происходит ошибка на этапе компиляции
Расположение массива в памяти
Операция индексирования массива
Большинство операций с массивами разумно проводить с помощью циклов, по очереди перебирая элементы
Циклическая обработка массива
Линейный поиск элемента в массиве
Бинарный поиск элемента в массиве
Сортировка массива прямым обменом (метод «пузырька»)
Сортировка массива прямыми вставками
Двумерный массив, как частный случай многомерного массива
Двумерный массив представляет собой совокупность строк и столбцов, на пересечении которых находится конкретное значение
Двумерный массив располагается в памяти построчно: сначала нулевая строка, затем первая и т.д.
Объявление двумерного массива
Инициализация массива
Циклическая обработка массива
Функции в процедурном программировании
Один и тот же код может встречаться в программе несколько раз
Например, применение алгоритмов суммирования, сортировки, определения максимального значения массива в практической задаче
Как следствие, увеличивается количество и затрудняется чтение программного кода
С увеличением объема программы становится невозможным хранить в человеческой памяти все ее детали
Одним из естественных вариантов борьбы со сложностью является алгоритмическая декомпозиция -разбиение задачи на подзадачи
Функция – это именованная последовательность описаний и операторов, выполняющая какое-либо законченное действие
Функция может принимать параметры и возвращать значение
Определение функции
Определение функции
Начало области видимости переменной совпадает с ее объявлением
В зависимости от места объявления различают два типа переменных: локальные и глобальные
Блок - область программного кода от открывающей до соответствующей закрывающей фигурной скобки
Локальная переменная
Конец области видимости локальной переменной совпадает с закрывающей фигурной скобкой, соответствующей открывающей фигурной
Локальные переменные создаются в специальной области оперативной памяти, которая называется стеком
Стек функционирует по правилу LIFO (Last In First Out)
Локальные переменные создаются при каждом вызове функции
После завершения работы функции соответствующий участок стека освобождается и локальные переменные функции уничтожаются
Поэтому значения локальных переменных между вызовами одной и той же функции не сохраняются
Глобальная переменная
Конец области видимости глобальной переменной в текущем файле совпадает с концом этого файла
Глобальные переменные создаются в специальной области оперативной памяти, которая называется сегментом данных
Глобальные переменные создаются до вызова функции main и по умолчанию инициализируются нулем
Глобальные переменные уничтожаются после окончания работы функции main
Значения глобальных переменных сохраняются между вызовами одной и той же функции
Глобальные переменные видны во всех функциях, где не объявлены локальные переменные с теми же именами
Поэтому очень легко их использовать для передачи данных между функциями
Однако использование глобальных переменных не рекомендуется, поскольку это препятствует помещению функций в библиотеки общего
Необходимо стремится к тому, чтобы функции были максимально независимы, а их интерфейс полностью определялся прототипом функции
Глобальная переменная может быть перекрыта локальной переменной с таким же именем
Статическая локальная переменная
Статические локальные переменные имеют такую же область видимости, что и обычные локальные переменные
Статические локальные переменные создаются в сегменте данных при первом вызове функции и по умолчанию инициализируются нулем
Статические локальные переменные уничтожаются после окончания работы функции main
Значения локальных статических переменных сохраняются между вызовами одной и той же функции
Перегрузка функций
Компилятор определяет, какую именно функцию требуется вызвать, по типу фактических параметров
Этот процесс называется разрешением перегрузки
Тип возвращаемого функцией значения в разрешении не участвует
Пример перегрузки функций
В процессе разрешения перегрузки компилятор выбирает функцию с наиболее подходящими параметрами
Пример перегрузки функций
Критерий разрешения перегрузки - однозначность вызова функции
Пример перегрузки функций
Пример перегрузки функций
Перегруженные функции должны находиться в одной области видимости, иначе произойдет сокрытие аналогично одинаковым именам
Пример перегрузки функций
Встраивание (Inline – функции)
Как известно, при вызове функции происходит:
Все это вносит издержки, которые немного влияют на скорость
Механизм встраивания предназначен для увеличения производительности кода
Встраивание (inline) - это техника, благодаря которой компилятор имеет возможность встроить (скопировать) код функции напрямую
Для того, чтобы сделать функцию встраиваемой, необходимо при определении функции указать ключевое слово inline
Если функция производит собственный вызов напрямую, то такая рекурсия называется прямой
Существует также косвенная рекурсия, когда две функции вызывают друг друга
Итерационный метод решения задач
Рекурсивный метод решения задач
Процесс рекурсивных вызовов
Для завершения вычислений каждая рекурсивная функция должна содержать хотя бы одну нерекурсивную ветвь алгоритма, которая
Достоинством рекурсии является компактная запись
Недостатки рекурсии – расход времени и памяти на повторные вызовы функции и передачу ей копий параметров
Главный недостаток рекурсии - опасность переполнения стека
Рекурсивные функции обычно применяют для работы с древовидными структурами данных
Адреса и указатели
В языке С++ используется плоская модель памяти (Flat model)
В плоской модели код и данные используют одно и то же адресное пространство
Каждый байт памяти имеет свой адрес
У каждой переменной есть свой адрес в памяти
Адрес переменной – это целое число, которое обозначает смещение переменной от начала памяти
Операция получения адреса – взятие адреса &
Указатель не является самостоятельным типом, он всегда связан с каким-либо другим конкретным типом
Базовый тип указателя определяется типом переменной, на которую он может ссылаться
Инициализация указателя
void * - это указатель без привязки к типу, т.е. обобщенный указатель
Операция разыменования указателя * – косвенная адресация
Разыменование указателя (косвенная адресация) – получение доступа к переменной, на которую ссылается указатель
Изменение значения указателя
Приоритет операций & и * выше, чем приоритет всех арифметических операторов, за исключением унарного минуса
Различная интерпретация оператора *
Указатель на переменную и указатель на константу
Указатель-константа на переменную и указатель-константа на константу
Размер указателя
В соответствии со стандартом C++, размер указателя зависит от конкретной реализации компилятора и не связан напрямую с
Однако на большинстве современных операционных систем размер указателя соответствует разрядности адресной шины у архитектуры
Ширина шины адреса определяет объём адресуемой памяти
Например, если ширина адресной шины составляет 32 бита, то объём памяти, который можно адресовать, составляет 2^32 байт или 4
Связь массивов и указателей
Имя массива без указания индексации - это адрес начала массива в оперативной памяти, т.е. адрес нулевого элемента массива
Использование операции индексирования для обращения к элементам массива
Расположение массива в памяти
Расположение массива в памяти
Использование операции разыменования для обращения к элементам массива
Результат действия выражения * (intarray + j) — тот же, что и выражения intarray[j]
Использование арифметики указателей
Использование арифметики указателей
Сравнение указателей
4.79M
Категория: ПрограммированиеПрограммирование

Процедурное программирование на языке C++

1.

Процедурное программирование
на языке C++
Виталий Полянский,
преподаватель кафедры
«Разработка программного обеспечения»
Одесского филиала Компьютерной Академии ШАГ

2.

Алгоритм – последовательность
действий, направленных на
достижение конкретного результата

3.

Программа – последовательность
команд (инструкций), выполняемых
процессором и описывающих алгоритм
на языке программирования

4.

Данные – информация, которая
обрабатывается в процессе
выполнения программы

5.

Машинный код

6.

Ассемблерный код

7.

Код на языке С

8.

Современные языки программирования

9. Основные преимущества языков низкого уровня

• Прямой доступ к аппаратным ресурсам
• Малый размер исполняемого файла
• Высокая скорость выполнения

10. Основной недостаток языков низкого уровня – сложность программирования из-за огромных размеров исходного кода

11. Главное преимущество языков высокого уровня – быстрота разработки сложных программных продуктов

12. Основные недостатки языков высокого уровня

• Ограниченный доступ к аппаратным ресурсам
• Большой размер исполняемого файла
• Сравнительно невысокая скорость выполнения

13. Основные этапы разработки программы

• Постановка задачи
• Проектирование
• Кодирование

14.

На этапе постановки задачи
программист выясняет у заказчика
требования к программе

15.

На этапе проектирования
программист выбирает алгоритм
для написания программы

16.

На этапе кодирования программист
переводит алгоритм на какой-либо
язык программирования

17. Этапы создания исполняемого файла (.exe)

18.

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

19.

Компилятор выявляет синтаксические
ошибки и, в случае их отсутствия,
строит объектный модуль (.obj)

20.

Компоновщик формирует
исполняемый модуль программы
(.exe) из объектных модулей (.obj) и
библиотечных файлов (.lib)

21. Литералы

• Строковый
• Символьный
• Целочисленный
• Вещественный
• Логический

22.

Строковый литерал –
последовательность символов,
заключенная в двойные кавычки
“The C Programming Language”

23.

Символьный литерал – одиночный
символ, заключенный в одинарные
кавычки
‘!’
‘A’
‘8’

24.

Целочисленный литерал – любое
положительное или отрицательное
целое число
-15
100
OxFF

25.

Вещественный литерал – дробное
число, представленное в форме с
десятичной точкой либо в
экспоненциальной форме
-5.7
5e10
11e-3

26. Логический литерал

• true (истина)
• false (ложь)

27.

Понятие переменной

28.

Переменная –
именованная область оперативной
памяти, предназначенная для хранения
изменяемого значения указанного типа

29. Типы данных

• Целочисленный
• Символьный
• Вещественный
• Логический

30. Целочисленные типы

• short (2 байта)
-32768 … 32767
• unsigned short (2 байта)
0 … 65535
• int (4 байта – зависит от разрядности
платформы и компилятора)
-2 147 483 648 … 2 147 483 647

31. Целочисленные типы

• unsigned int (4 байта – зависит от
архитектуры платформы и компилятора)
0 … 4 294 967 295
• long (4 байта)
-2 147 483 648 … 2 147 483 647
• unsigned long (4 байта)
0 … 4 294 967 295

32. Целочисленные типы

• long long (8 байт)
-9 223 372 036 854 775 808 …
9 223 372 036 854 775 807
• unsigned long long (8 байт)
0 … 18 446 744 073 709 551 615

33.

Тип данных int строго не определён
стандартом языка и должен иметь
«естественный» размер с учётом
архитектуры (разрядности) системы

34.

Тип данных int не должен быть
меньше short (2 байта) и не
должен превышать long (4 байта)

35. Символьные типы

• char(1 байт)
-128 … 127
• unsigned char (1 байт)
0 … 255

36.

Тип данных char представляет один
символ в кодировке ASCII

37.

ASCII (American standard code
for information interchange) — название
таблицы (кодировки), в которой
символам сопоставлены числовые коды

38.

39.

Например, символу ‘D’
соответствует ASCII-код 68, а
символу ‘d’ – ASCII-код 100

40. Вещественные типы

• float (4 байта)
3.4E-38 … 3.4E+38
• double (8 байт)
1.7E-308 … 1.7E+308

41. Логический тип

• bool (1 байт)
true false

42.

Для того чтобы использовать в
программе переменную, ее
необходимо объявить

43.

Синтаксис объявления переменных:
тип_переменной имя_переменной;

44.

Имя переменной называется
идентификатором

45. Правила именования идентификаторов:

• Имя переменной не может начинаться с цифры
• Имя переменной может содержать буквы,
цифры и знак подчеркивания «_»
• Имя переменной не может являться ключевым
или служебным словом
• Имя переменной должно быть уникальным
• Имя переменной должно быть осмысленным

46.

47.

Константа –
именованная область оперативной
памяти, предназначенная для хранения
постоянного значения указанного типа

48.

Синтаксис объявления константы:
const тип_константы имя_ константы =
значение;

49.

Литералы, рассмотренные ранее,
представляют собой константы,
непосредственно включаемые в текст
программы

50.

Литералы отличаются от констант тем,
что они не имеют идентификаторов

51.

Ввод данных

52.

Синтаксис ввода данных:
cin >> имя_переменной;

53.

54.

Понятие оператора

55.

Оператор – это конструкция языка
программирования, которая выполняет
определённое действие над
аргументами (операндами)

56.

Операнд - это аргумент оператора, то
есть то значение, над которым оператор
выполняет действие

57. В зависимости от количества операндов операторы бывают:

• Унарные
• Бинарные
• Тернарные

58.

Оператор присваивания

59.

Синтаксис оператора присваивания:
имя_переменной = выражение;

60.

Выражение –
конструкция, состоящая из операндов,
объединенных знаками операций

61.

62.

Множественные присваивания присваивания одного и того же
значения нескольким переменным
одновременно

63. Арифметические операторы

• Оператор сложения (бинарный)
• Оператор вычитания (бинарный)
• Оператор умножения (бинарный)
• Оператор деления (бинарный)

64. Арифметические операторы

• Оператор остаток от деления (бинарный)
• Оператор минус (унарный)
• Оператор инкремент (унарный)
• Оператор декремент (унарный)

65. Сокращённые формы операторов: += -= *= /= %=

66.

Приведение типов

67.

Выражение –
конструкция, состоящая из операндов,
объединенных знаками операций

68.

Результат вычисления выражения
характеризуется значением и типом

69.

В выражение могут входить операнды
различных типов

70.

Если операнды имеют
одинаковый тип, то результат
операции будет иметь тот же тип

71.

Если операнды разного типа, перед
вычислениями выполняются
преобразования типов по
определенным правилам

72.

Эти правила обеспечивают
преобразование более коротких типов
в более длинные для сохранения
значимости и точности

73.

74.

75.

Перед вычислением выражения
смешанного типа происходит неявное
(автоматическое) расширяющее
преобразование операндов

76.

Неявное расширяющее
преобразование типа может также
происходить при присваивании
переменной результата выражения

77.

Неявное преобразование типа при
присваивании переменной результата
выражения может быть сужающим

78. Сужающие преобразования бывают:

• с потерей точности (данных)
• с переполнением разрядной сетки
• с изменением интерпретации
внутреннего представления данных

79.

Приведение типов может быть явным

80.

Явное приведение типов указывается
программистом в коде программы

81.

Синтаксис явного приведения типа:
(тип) выражение;

82.

83.

Структура ветвления

84. Операторы отношения

• == (равно)
• != (не равно)
• > (больше)
• >= (больше либо равно)
• < (меньше)
• <= (меньше либо равно)

85.

Операторы отношения
предназначены для составления
логических выражений

86.

Результат вычисления любого
логического выражения –
ИСТИНА или ЛОЖЬ

87.

88. Логические операторы

• && (логическое умножение, логическое И)
• || (логическое сложение, логическое ИЛИ)
• ! (логическое отрицание, логическое НЕ)

89.

Логические операторы предназначены
для объединения логических
выражений

90.

91. Логическое «ИЛИ»

5 == 5 || 5 == 9
// true, потому что первое выражение true
5 > 3 || 5 > 10
// true, потому что первое выражение true
5 > 8 || 5 < 10
// true, потому что второе выражение true
5 < 8 || 5 > 2
// true, потому что оба выражения true
5 > 8 || 5 < 2
// false, потому что оба выражения false

92. Логическое «И»

5 == 5 && 4 == 4
// true, потому что оба выражения true
5 == 3 && 4 == 4
// false, потому что первое выражение false
5 > 3 && 5 > 10
// false, потому что второе выражение false
5 < 8 && 5 > 2
// true, потому что оба выражения true
5 > 8 && 5 < 2
// false, потому что оба выражения false

93. Логическое «НЕ»

!(10 != 10)
// true, потому что выражение false
!(5 > 3)
// false, потому что выражение true

94. Оператор ветвления «if»

if (выражение)
{
// оператор_1;
}
else
{
// оператор_2;
}

95. Оператор ветвления «if»

if (выражение)
{
// оператор;
}

96. Оператор ветвления «if»

if (выражение_1)
{ // оператор_1; }
else if (выражение_2)
{ // оператор_2; }
else
{ // оператор_3; }

97.

Таблица приоритетов операций

98.

Структура повторения

99.

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

100.

В языке программирования С++
структура повторения реализуется с
помощью оператора цикла

101. Виды циклов

• Цикл с предусловием (while)
• Цикл с постусловием (do while)
• Параметрический цикл (for)

102. Цикл с предусловием while

while (выражение)
{
// оператор
// или группа
// операторов
}

103. Цикл с постусловием do while

do
{
// оператор
// или группа
// операторов
}
while (выражение);

104. Параметрический цикл for

105.

Массивы

106.

Массив –
это совокупность переменных,
объединенных под общим именем и
имеющих один и тот же тип данных

107.

Каждая переменная в массиве
является самостоятельной единицей и
называется элементом массива

108.

Все элементы массива располагаются в
памяти последовательно друг за другом
и имеют свой индекс – смещение
относительно начала массива

109. Объявление массива

Синтаксис объявления массива:
тип_данных имя_массива[количество_элементов];
int numbers[4];
const int nSize = 6;
double arr[nSize];

110. Инициализация массива

тип_данных имя_массива[количество элементов] =
{значение1, значение2, ... значение n};

111. Количество элементов массива можно не указывать. Размер массива определяется исходя из числа элементов в списке инициализации.

int arrayInit[] = { 2, 33, 4 }; // массив из трех элементов

112. Если значений в списке инициализации меньше чем количество элементов массива, то оставшиеся значения автоматически заполняются

нулями
int arr[6] = { 1, 2, 3 };
// такая запись эквивалентна записи:
int arr[6] = { 1, 2, 3, 0, 0, 0 };

113. Если значений в списке инициализации больше чем количество элементов массива, то происходит ошибка на этапе компиляции

// int arr[2] = {1, 2, 3}; // Ошибка на этапе компиляции

114. Расположение массива в памяти

Формула, согласно которой производится позиционирование
по массиву:
базовый адрес + размер базового типа * индекс;

115. Операция индексирования массива

Операция индексирования массива
Запись значения в массив:
имя_массива[индекс_элемента] = значение;
Получение значения из массива:
cout << имя_массива[индекс_элемента];
const int nArraySize = 3;
int ar[nArraySize];
ar[1] = 7;
cout << ar[1] << endl;

116. Большинство операций с массивами разумно проводить с помощью циклов, по очереди перебирая элементы

117. Циклическая обработка массива

118. Линейный поиск элемента в массиве

119. Бинарный поиск элемента в массиве

120. Сортировка массива прямым обменом (метод «пузырька»)

121. Сортировка массива прямыми вставками

122. Двумерный массив, как частный случай многомерного массива

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

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

125. Объявление двумерного массива

Синтаксис объявления двумерного массива:
тип_данных имя_массива [число_строк][число_столбцов];
const int ROW = 3; // строки
const int COL = 4; // столбцы
int arr[ROW][COL]; // массив размером 3х4

126. Инициализация массива

• Каждая строка заключается в отдельные фигурные скобки
int arr[2][2] = { { 1, 2 }, { 7, 8 } };
• Если значение пропущено, оно будет инициализировано
нулем
int arr[3][3] = { { 7, 8 }, { 10, 3, 5 } };
• Значения указываются подряд и построчно вписываются в
массив
int arr[2][2] = { 7, 8, 10, 3 };

127. Циклическая обработка массива

128. Функции в процедурном программировании

129. Один и тот же код может встречаться в программе несколько раз

130. Например, применение алгоритмов суммирования, сортировки, определения максимального значения массива в практической задаче

могут
встречаться очень часто

131. Как следствие, увеличивается количество и затрудняется чтение программного кода

132. С увеличением объема программы становится невозможным хранить в человеческой памяти все ее детали

133. Одним из естественных вариантов борьбы со сложностью является алгоритмическая декомпозиция -разбиение задачи на подзадачи

Одним из естественных вариантов
борьбы со сложностью является
алгоритмическая декомпозиция разбиение задачи на подзадачи

134.

Процедурное программирование –
подход, при котором исходная задача
разбивается на подзадачи, каждая из
которых оформляется в виде функции

135. Функция – это именованная последовательность описаний и операторов, выполняющая какое-либо законченное действие

136. Функция может принимать параметры и возвращать значение

137. Определение функции

Синтаксис определения функции:
<тип> <имя_функции> ([список параметров])
{
тело функции
}

138. Определение функции

139.

Область видимости переменной–
это некоторая область программы,
внутри которой возможно обратиться к
переменной

140. Начало области видимости переменной совпадает с ее объявлением

141. В зависимости от места объявления различают два типа переменных: локальные и глобальные

142.

Локальная переменная –
переменная, объявленная внутри
функции или блока

143. Блок - область программного кода от открывающей до соответствующей закрывающей фигурной скобки

144. Локальная переменная

145. Конец области видимости локальной переменной совпадает с закрывающей фигурной скобкой, соответствующей открывающей фигурной

скобке, после
которой была объявлена переменная

146. Локальные переменные создаются в специальной области оперативной памяти, которая называется стеком

147. Стек функционирует по правилу LIFO (Last In First Out)

148. Локальные переменные создаются при каждом вызове функции

149. После завершения работы функции соответствующий участок стека освобождается и локальные переменные функции уничтожаются

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

151.

Глобальная переменная –
переменная, объявленная вне функции

152. Глобальная переменная

153. Конец области видимости глобальной переменной в текущем файле совпадает с концом этого файла

154. Глобальные переменные создаются в специальной области оперативной памяти, которая называется сегментом данных

155. Глобальные переменные создаются до вызова функции main и по умолчанию инициализируются нулем

156. Глобальные переменные уничтожаются после окончания работы функции main

157. Значения глобальных переменных сохраняются между вызовами одной и той же функции

158. Глобальные переменные видны во всех функциях, где не объявлены локальные переменные с теми же именами

159. Поэтому очень легко их использовать для передачи данных между функциями

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

пользования

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

162. Глобальная переменная может быть перекрыта локальной переменной с таким же именем

163.

Статическая локальная переменная –
переменная, объявленная внутри
функции или блока

164. Статическая локальная переменная

165. Статические локальные переменные имеют такую же область видимости, что и обычные локальные переменные

166. Статические локальные переменные создаются в сегменте данных при первом вызове функции и по умолчанию инициализируются нулем

167. Статические локальные переменные уничтожаются после окончания работы функции main

168. Значения локальных статических переменных сохраняются между вызовами одной и той же функции

169. Перегрузка функций

170.

Перегруженные функции –
это функции, которые имеют
одинаковые имена, но отличаются
сигнатурой

171.

Сигнатура –
это тип, количество и порядок
следования формальных параметров
функции

172. Компилятор определяет, какую именно функцию требуется вызвать, по типу фактических параметров

173. Этот процесс называется разрешением перегрузки

174. Тип возвращаемого функцией значения в разрешении не участвует

175. Пример перегрузки функций

176. В процессе разрешения перегрузки компилятор выбирает функцию с наиболее подходящими параметрами

177. Пример перегрузки функций

178. Критерий разрешения перегрузки - однозначность вызова функции

Критерий разрешения перегрузки однозначность вызова функции

179. Пример перегрузки функций

180. Пример перегрузки функций

181. Перегруженные функции должны находиться в одной области видимости, иначе произойдет сокрытие аналогично одинаковым именам

переменных во
вложенных блоках

182. Пример перегрузки функций

183. Встраивание (Inline – функции)

184. Как известно, при вызове функции происходит:


Помещение аргументов в стек
Передача управления функции
Возврат из функции
Освобождение стека

185. Все это вносит издержки, которые немного влияют на скорость

186. Механизм встраивания предназначен для увеличения производительности кода

187. Встраивание (inline) - это техника, благодаря которой компилятор имеет возможность встроить (скопировать) код функции напрямую

в место её вызова

188. Для того, чтобы сделать функцию встраиваемой, необходимо при определении функции указать ключевое слово inline

189.

В этом случае компилятору
рекомендуется не использовать
привычный вызов функции, а встроить
её код напрямую в место использования

190.

Однако встраивание является
рекомендацией для компилятора
и срабатывает не всегда

191.

Встраивание проходит для очень
простых функций, состоящих из
нескольких инструкций, которые
не содержат сложных конструкций

192.

Если функция содержит сложные
конструкции (циклы, if/else, switch
и т.д.), то компилятор может
проигнорировать встраивание

193.

В таком случае, inline-функция ничем не
будет отличаться от обычной

194.

Шаблоны функций

195.

Шаблоны используются, когда
необходимо создать функции, которые
применяют один и тот же алгоритм к
различным типам данных

196.

Шаблон функции – это
обобщенное описание функции

197.

У такой функции хотя бы один
формальный параметр имеет
обобщенный тип

198.

Определение шаблона функции

199.

Использование шаблона функции

200.

В момент вызова функции компилятор
автоматически создает
специализированную версию функции,
где вместо параметра типа
подставляется конкретный тип данных

201.

Этот процесс называется
инстанцированием шаблона или
созданием экземпляра шаблона

202.

Повторный вызов функции с теми же
типами параметров не спровоцирует
генерацию дополнительной копии
функции, а вызовет уже существующую

203.

Использование шаблона функции

204.

Определение шаблона функции не
вызывает самостоятельную генерацию
кода компилятором

205.

По этой причине реализацию шаблонов
функций следует размещать в
заголовочном файле

206.

Компилятор создает код функции только
в момент ее вызова, и генерирует при
этом соответствующую версию функции

207.

Перегруженные шаблоны

208.

Важно понимать, что использование
шаблонов функций не приводит к
уменьшению результирующего
объектного кода

209.

Однако экономит время
разработки программы

210.

Рекурсия

211.

Рекурсивная функция–
функция, которая вызывает сама себя

212. Если функция производит собственный вызов напрямую, то такая рекурсия называется прямой

213. Существует также косвенная рекурсия, когда две функции вызывают друг друга

214. Итерационный метод решения задач

215. Рекурсивный метод решения задач

216. Процесс рекурсивных вызовов

217. Для завершения вычислений каждая рекурсивная функция должна содержать хотя бы одну нерекурсивную ветвь алгоритма, которая

заканчивается
оператором возврата

218. Достоинством рекурсии является компактная запись

219. Недостатки рекурсии – расход времени и памяти на повторные вызовы функции и передачу ей копий параметров

220. Главный недостаток рекурсии - опасность переполнения стека

Главный недостаток рекурсии опасность переполнения стека

221. Рекурсивные функции обычно применяют для работы с древовидными структурами данных

222. Адреса и указатели

223. В языке С++ используется плоская модель памяти (Flat model)

224.

225. В плоской модели код и данные используют одно и то же адресное пространство

226. Каждый байт памяти имеет свой адрес

227. У каждой переменной есть свой адрес в памяти

228.

Адрес переменной –
это целочисленное значение, индекс
первого байта области памяти, которую
занимает переменная

229. Адрес переменной – это целое число, которое обозначает смещение переменной от начала памяти

230. Операция получения адреса – взятие адреса &

Операция получения адреса –
взятие адреса &

231.

Указатель –
это переменная, значением которой
является адрес другой переменной

232. Указатель не является самостоятельным типом, он всегда связан с каким-либо другим конкретным типом

233. Базовый тип указателя определяется типом переменной, на которую он может ссылаться

234. Инициализация указателя

235. void * - это указатель без привязки к типу, т.е. обобщенный указатель

236. Операция разыменования указателя * – косвенная адресация

237. Разыменование указателя (косвенная адресация) – получение доступа к переменной, на которую ссылается указатель

238. Изменение значения указателя

239.

240.

241. Приоритет операций & и * выше, чем приоритет всех арифметических операторов, за исключением унарного минуса

Приоритет операций & и * выше, чем
приоритет всех арифметических
операторов, за исключением унарного
минуса

242. Различная интерпретация оператора *

243. Указатель на переменную и указатель на константу

244. Указатель-константа на переменную и указатель-константа на константу

245. Размер указателя

246. В соответствии со стандартом C++, размер указателя зависит от конкретной реализации компилятора и не связан напрямую с

разрядностью
используемой платформы

247. Однако на большинстве современных операционных систем размер указателя соответствует разрядности адресной шины у архитектуры

этих платформ

248. Ширина шины адреса определяет объём адресуемой памяти

249. Например, если ширина адресной шины составляет 32 бита, то объём памяти, который можно адресовать, составляет 2^32 байт или 4

Гбайт

250. Связь массивов и указателей

251. Имя массива без указания индексации - это адрес начала массива в оперативной памяти, т.е. адрес нулевого элемента массива

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

252. Использование операции индексирования для обращения к элементам массива

253. Расположение массива в памяти

254. Расположение массива в памяти

Формула, согласно которой производится позиционирование
по массиву:
базовый адрес + размер базового типа * индекс;

255. Использование операции разыменования для обращения к элементам массива

256. Результат действия выражения * (intarray + j) — тот же, что и выражения intarray[j]

257. Использование арифметики указателей

258. Использование арифметики указателей

259. Сравнение указателей

English     Русский Правила