Инициализация в стеке
Часть раздела Object Oriented Programming путешествия по C на Coddy — урок 14 из 61.
Не каждому объекту нужно находиться в куче. Когда структура невелика и имеет короткий жизненный цикл, выделение её в стеке проще и быстрее — ни malloc, ни free, никакого риска утечек памяти.
Вместо возврата указателя, фабричная функция может возвращать структуру по значению. Вся структура копируется вызывающей стороне:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
Вызывающая сторона получает полностью инициализированную копию:
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
Никаких указателей, очистка не требуется. Когда origin и cursor выходят из области видимости, они автоматически уничтожаются.
Этот подход лучше всего работает для небольших структур без динамически распределяемых членов. Для более крупных объектов или объектов, содержащих указатели на память в куче, паттерн конструктора с malloc остается лучшим выбором.
Задание
ЛегкоДавайте создадим модуль Temperature, который создает показания температуры в стеке с помощью фабричной функции. В отличие от конструкторов на основе кучи из предыдущих уроков, этот подход возвращает структуру по значению — без malloc, без free, простое и эффективное выделение памяти в стеке.
Вы создадите три файла:
temperature.h: Объявите структуруTemperatureс двумя полями:double celsiusиchar scale(для хранения 'C' для Цельсия). Также объявите две функции:create_temperature— принимает значение double и возвращает структуруTemperatureпо значению (не указатель!)temperature_to_fahrenheit— принимаетconst Temperature *и возвращает эквивалентную температуру в Фаренгейтах в виде double
TEMPERATURE_H.temperature.c: Реализуйте обе функции. Ваша фабричная функция должна создать локальную переменнуюTemperature, инициализировать ее поля (установитьscaleв'C') и вернуть ее. Формула преобразования:fahrenheit = celsius * 9.0 / 5.0 + 32.0main.c: Используйте свою фабричную функцию для создания показания температуры и выведите значения как в Цельсиях, так и в Фаренгейтах.
Вы получите один входной параметр: температуру в градусах Цельсия (в виде double).
В вашем основном файле используйте create_temperature для создания структуры Temperature с заданным значением. Затем выведите исходное значение в Цельсиях и его эквивалент в Фаренгейтах.
Выведите результат в следующем формате:
Celsius: {celsius}
Fahrenheit: {fahrenheit}Используйте %.2f для обоих значений, чтобы отобразить два знака после запятой.
Например, при входном значении 25.0 вывод будет следующим:
Celsius: 25.00
Fahrenheit: 77.00Обратите внимание, насколько чист этот подход — вы получаете полностью инициализированную структуру без каких-либо забот об управлении памятью. Когда ваша переменная Temperature выходит за пределы области видимости, она очищается автоматически.
Шпаргалка
Фабричные функции могут возвращать структуры по значению вместо указателей. Это размещает структуру в стеке — без malloc, без free и без утечек памяти.
Пример фабричной функции, возвращающей значение:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
Использование фабричной функции:
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
Структура копируется вызывающей стороне и автоматически уничтожается при выходе из области видимости. Этот подход лучше всего подходит для небольших структур без динамически выделяемых членов.
Попробуйте сами
#include <stdio.h>
#include "temperature.h"
int main() {
double celsius_input;
scanf("%lf", &celsius_input);
// TODO: Используйте create_temperature для создания структуры Temperature
// TODO: Выведите значение Celsius, используя формат %.2f
// TODO: Используйте temperature_to_fahrenheit для преобразования и вывода значения Fahrenheit
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Object Oriented Programming
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация круга