Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Этот формат присвоения нескольким переменным общего значения можно часто встретить в профессионально написанных программах.
Использование ключевого слова sizeof Иногда полезно знать размер (в байтах) одного из типов данных. Поскольку размеры встроенных С++-типов данных в разных вычислительных средах могут быть различными, а знание размера переменной во всех ситуациях имеет важное значение, то для решения этой проблемы в C++ включен оператор (действующий во время компиляции программы), который используется в двух следующих форматах. Sizeof (type) Sizeof value Оператор sizeof во время компиляции программы получает размер типа или значения. Первая версия возвращает размер заданного типа данных, а вторая — размер заданного значения. Если вам нужно узнать размер некоторого типа данных (например, int), заключите название этого типа в круглые скобки. Если же вас интересует размер области памяти, занимаемой конкретным значением, можно обойтись без круглых скобок, хотя при желании их можно использовать. Чтобы понять, как работает оператор sizeof, испытайте следующую короткую программу. Для многих 32-разрядных сред она должна отобразить значения 1, 4, 4 и 8. // Демонстрация использования оператора sizeof. #include < iostream> using namespace std; Int main() { char ch; int i; cout < < sizeof ch < < ' '; // размер типа char cout < < sizeof i < < ' '; // размер типа int cout < < sizeof (float) < < ' '; // размер типа float cout < < sizeof (double) < < ' '; // размер типа double return 0; } Как упоминалось выше, оператор sizeof действует во время компиляции программы. Вся информация, необходимая для вычисления размера указанной переменной или заданного типа данных, известна уже во время компиляции. Оператор sizeof можно применить к любому типу данных. Например, в случае применения к массиву он возвращает количество байтов, занимаемых массивом. Рассмотрим следующий фрагмент кода. int nums[4]; cout < < sizeof nums; // Будет выведено число 16. Для 4-байтных значений типа int при выполнении этого фрагмента кода на экране отобразится число 16 (которое получается в результате умножения 4 байт на 4 элемента массива). Оператор sizeof главным образом используется при написании кода, который зависит от размера С++-типов данных. Помните: поскольку размеры типов данных в C++ определяются конкретной реализацией, не стоит полагаться на размеры типов, определенные в реализации, в которой вы работаете в данный момент. Динамическое распределение памяти с использованием операторов new и delete Для С++-программы существует два основных способа хранения информации в основной памяти компьютера. Первый состоит в использовании переменных. Область памяти, предоставляемая переменным, закрепляется за ними во время компиляции и не может быть изменена при выполнении программы. Второй способ заключается в использовании C++-системы динамического распределения памяти. В этом случае память для данных выделяется по мере необходимости из раздела свободной памяти, который расположен между вашей программой (и ее постоянной областью хранения) и стеком. Этот раздел называется " кучей" (heap). (Расположение программы в памяти схематично показано на рис. 9.2.) Система динамического распределения памяти — это средство получения программой некоторой области памяти во время ее выполнения. Динамическое выделение памяти — это получение программой памяти во время ее выполнения. Другими словами, благодаря этой системе программа может создавать переменные во время выполнения, причем в нужном (в зависимости от ситуации) количестве. Эта система динамического распределения памяти особенно ценна для таких структур данных, как связные списки и двоичные деревья, которые изменяют свой размер по мере их использования. Динамическое выделение памяти для тех или иных целей — важная составляющая почти всех реальных программ. Чтобы удовлетворить запрос на динамическое выделение памяти, используется так называемая " куча" . Нетрудно предположить, что в некоторых чрезвычайных ситуациях свободная память " кучи" может исчерпаться. Следовательно, несмотря на то, что динамическое распределение памяти (по сравнению с фиксированным) обеспечивает большую гибкость, но и в этом случае оно имеет свои пределы. Оператор new позволяет динамически выделить область памяти. Язык C++ содержит два оператора, new и delete, которые выполняют функции по выделению и освобождению памяти. Приводим их общий формат. переменная-указатель = new тип_переменной; delete переменная-указатель; Оператор delete освобождает ранее выделенную динамическую память. Здесь элемент переменная-указатель представляет собой указатель на значение, тип которого задан элементом тип_переменной. Оператор new выделяет область памяти, достаточную для хранения значения заданного типа, и возвращает указатель на эту область памяти. С помощью оператора new можно выделить память для значений любого допустимого типа. Оператор delete освобождает область памяти, адресуемую заданным указателем. После освобождения эта память может быть снова выделена в других целях при последующем new-запросе на выделение памяти. Поскольку объем " кучи" конечен, она может когда-нибудь исчерпаться. Если для удовлетворения очередного запроса на выделение памяти не существует достаточно свободной памяти, оператор new потерпит фиаско, и будет сгенерировано исключение. Исключение— это ошибка специального типа, которая возникает во время выполнения программы (в C++ предусмотрена целая подсистема, предназначенная для обработки таких ошибок). (Исключения описаны в главе 17.) В общем случае ваша программа должна обработать подобное исключение и по возможности выполнить действие, соответствующее конкретной ситуации. Если это исключение не будет обработано вашей программой, ее выполнение будет прекращено. Такое поведение оператора new в случае невозможности удовлетворить запрос на выделение памяти определено стандартом C++. На такую реализацию настроены также все современные компиляторы, включая последние версии Visual C++ и C++ Builder. Однако дело в том, что некоторые более ранние компиляторы обрабатывают new-инструкции по-другому. Сразу после изобретения языка C++ оператор new при неудачном выполнении возвращал нулевой указатель. Позже его реализация была изменена так, чтобы в случае неудачи генерировалось исключение, как было описано выше. Поскольку в этой книге мы придерживаемся стандарта C++, то во всех представленных здесь примерах предполагается именно генерирование исключения. Если же вы используете более старый компилятор, обратитесь к прилагаемой к нему документации и уточните, как реализован оператор new (при необходимости внесите в примеры соответствующие изменения). Поскольку исключения рассматриваются ниже в этой книге (после темы классов и объектов), мы не будем пока отвлекаться на обработку исключений, генерируемых в случае неудачного выполнения оператора new. Кроме того, ни один из примеров в этой и последующих главах не должен вызвать неудачного выполнения оператора new, поскольку в этих программах запрашивается лишь несколько байтов. Но если такая ситуация все же возникнет, то в худшем случае это приведет к завершению программы. В главе 17, посвященной обработке исключений, вы узнаете, как обработать исключение, сгенерированное оператором new. Рассмотрим пример программы, которая иллюстрирует использование операторов new и delete. #include < iostream> using namespace std; Int main() { int *p; p = new int; // Выделяем память для int-значения. *p = 20; // Помещаем в эту область памяти значение 20. cout < < *р; // Убеждаемся (путем вывода на экран) в работоспособности этого кода. delete р; // Освобождаем память. return 0; } Эта программа присваивает указателю р адрес (взятой из " кучи" ) области памяти, которая будет иметь размер, достаточный для хранения целочисленного значения. Затем в эту область памяти помещается число 20, после чего на экране отображается ее содержимое. Наконец, динамически выделенная память освобождается. Благодаря такому способу организации динамического выделения памяти оператор delete необходимо использовать только с тем указателем на память, который был возвращен в результате new-запроса на выделение памяти. Использование оператора delete с другим типом адреса может вызвать серьезные проблемы. Инициализация динамически выделенной памяти Используя оператор new, динамически выделяемую память можно инициализировать. Для этого после имени типа задайте начальное значение, заключив его в круглые скобки. Например, в следующей программе область памяти, адресуемая указателем p, инициализируется значением 99. #include < iostream> using namespace std; Int main() { int *p; p = new int (99); // Инициализируем память числом 99. cout < < *p; // На экран выводится число 99. delete p; return 0; } Выделение памяти для массивов С помощью оператора new можно выделять память и для массивов. Вот как выглядит общий формат операции выделения памяти для одномерного массива: переменная-указатель = new тип [размер]; Здесь элемент размер задает количество элементов в массиве. Чтобы освободить память, выделенную для динамически созданного массива, используйте такой формат оператора delete: delete [] переменная-указатель; Здесь элемент переменная-указатель представляет собой адрес, полученный при выделении памяти для массива (с помощью оператора new). Квадратные скобки означают для C++, что динамически созданный массив удаляется, а вся область памяти, выделенная для него, автоматически освобождается. Важно! Более старые С++-компиляторы могут требовать задания размера удаляемого массива, поскольку в ранних версиях C++ для освобождения памяти, занимаемой удаляемым массивом, необходимо было применять такой формат оператора delete: delete [размер] переменная-указатель; Здесь элемент размер задает количество элементов в массиве. Стандарт C++ больше не требует указывать размер при его удалении. При выполнении следующей программы выделяется память для 10-элементного массива типа double, который затем заполняется значениями от 100 до 109, после чего содержимое этого массива отображается на экране. #include < iostream> using namespace std; Int main() { double *p; int i; p = new double [10]; // Выделяем память для 10-элементного массива. //Заполняем массив значениями от 100 до 109. for(i=0; i< 10; i++) р[i] = 100.00 + i; // Отображаем содержимое массива. for(i=0; i< 10; i++) cout < < p[i] < < " "; delete [] p; // Удаляем весь массив. return 0; } Популярное:
|
Последнее изменение этой страницы: 2016-03-17; Просмотров: 1260; Нарушение авторского права страницы