Чтение онлайн

на главную

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

typedef struct bs_string { /* ... */ } bs_string; /* строка

Бьярне */

typedef int bs_bool; /* булев тип Бьярне */

/* in pete.h: */

typedef char* pete_string; /* строка Пита */

typedef char pete_bool; /* булев тип Пита */

Этот прием настолько широко используется, что использовать одно- и двухбуквенные префиксы обычно уже недостаточно.

27.4.

Свободная память

В языке С нет операторов

new
и
delete
, работающих с объектами. Для использования свободной памяти в нем используются функции, работающие с памятью. Наиболее важные функции определены в стандартном заголовочном файле общих утилит
<stdlib.h>
.

void* malloc(size_t sz); /* выделить sz байтов */

void free(void* p); /* освободить область памяти, на которую

ссылается указатель p */

void* calloc(size_t n, size_t sz); /* выделить n*sz байтов,

инициализировав их нулями */

void* realloc(void* p, size_t sz); /* вновь выделить sz байтов

в памяти, на которую ссылается

указатель p*/

Тип

typedef size_t
— это тип без знака, также определенный в заголовочном файле
<stdlib.h>
.

Почему функция
malloc
возвращает указатель
void*
? Потому что она не имеет информации о том, объект какого типа вы хотите разместить в памяти. Инициализация — это ваша проблема. Рассмотрим пример.

struct Pair {

const char* p;

int val;

};

struct Pair p2 = {"apple",78};

struct Pair* pp = (struct Pair*) malloc(sizeof(Pair)); /* выделить
память */

pp–>p = "pear"; /* инициализировать */

pp–>val = 42;

Теперь мы не можем написать инструкцию

*pp = {"pear", 42}; /* ошибка: не C и не C++98 */

ни в программе на языке C, ни в программе на языке C++. Однако в языке С++ мы могли бы определить конструктор для структуры

Pair
и написать инструкцию
Pair* pp = new Pair("pear", 42)
;

В языке C (но не в языке C++; см. раздел 27.3.4) перед вызовом функции malloc можно не указывать приведение типа, но мы не рекомендуем это делать.

int* p = malloc(sizeof(int)*n); /* избегайте этого */

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

программист забывает включить в текст программы заголовочный файл
<stdlib.h>
перед использованием функции
malloc
. Однако при этом исчезает и визуальный маркер, свидетельствующий о том, что размер памяти подсчитан неправильно.

p = malloc(sizeof(char)*m); /* вероятно, ошибка — нет места для m целых */

Не используйте функции
malloc/free
в программах, написанных на языке C++; операторы
new/delete
не требуют приведения типа, выполняют инициализацию (вызывая конструкторы) и очищают память (вызывая деструкторы), сообщают об ошибках, связанных с распределением памяти (с помощью исключений), и просто работают быстрее. Не удаляйте объект, размещенный в памяти с помощью функции
malloc
, выполняя оператор
delete
, и не удаляйте объект, созданный с помощью оператора new, вызывая функцию
free
. Рассмотрим пример.

int* p = new int[200];

// ...

free(p); // ошибка

X* q = (X*)malloc(n*sizeof(X));

// ...

delete q; // error

Этот код может оказаться вполне работоспособным, но он не является переносимым. Более того, для объектов, имеющих конструкторы и деструкторы, смешение стилей языков C и C++ при управлении свободной памятью может привести к катастрофе. Для расширения буферов обычно используется функция

realloc
.

int max = 1000;

int count = 0;

int c;

char* p = (char*)malloc(max);

while ((c=getchar)!=EOF) { /* чтение: игнорируются символы

в конце файла */

if (count==max–1) { /* необходимо расширить буфер */

max += max; /* удвоить размер буфера */

p = (char*)realloc(p,max);

if (p==0) quit;

}

p[count++] = c;

}

Объяснения операторов ввода в языке С приведены в разделах 27.6.2 и Б.10.2.

Функция
realloc
может выделить память на прежнем участке, а может и перенести его содержимое во вновь выделенную область памяти. Даже не думайте применять функцию
realloc
к области памяти, выделенной с помощью оператора
new
.

Используя стандартную библиотеку языка C++, этот код можно переписать примерно так:

Поделиться:
Популярные книги

Конструктор

Семин Никита
1. Переломный век
Фантастика:
попаданцы
альтернативная история
4.50
рейтинг книги
Конструктор

Афганский рубеж

Дорин Михаил
1. Рубеж
Фантастика:
попаданцы
альтернативная история
7.50
рейтинг книги
Афганский рубеж

Колючка для высшего эльфа или сиротка в академии

Жарова Анита
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Колючка для высшего эльфа или сиротка в академии

Имперец. Том 4

Романов Михаил Яковлевич
3. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Имперец. Том 4

Совок 2

Агарев Вадим
2. Совок
Фантастика:
альтернативная история
7.61
рейтинг книги
Совок 2

Кровь и Пламя

Михайлов Дем Алексеевич
7. Изгой
Фантастика:
фэнтези
8.95
рейтинг книги
Кровь и Пламя

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

Внешняя Зона

Жгулёв Пётр Николаевич
8. Real-Rpg
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Внешняя Зона

Приручитель женщин-монстров. Том 1

Дорничев Дмитрий
1. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 1

Камень

Минин Станислав
1. Камень
Фантастика:
боевая фантастика
6.80
рейтинг книги
Камень

Шесть тайных свиданий мисс Недотроги

Суббота Светлана
Любовные романы:
любовно-фантастические романы
эро литература
7.75
рейтинг книги
Шесть тайных свиданий мисс Недотроги

Измена. Мой непрощённый

Соль Мари
2. Самойловы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Мой непрощённый

Внешники

Кожевников Павел
Вселенная S-T-I-K-S
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Внешники

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач