|
Программирование >> Инициализация объектов класса, структура
auto ptr< string > pstr auto( new string( Brontosaurus ) ); ошибка: теперь оба указывают на один объект и оба являются его владельцами объектам. Менее очевидный - с помощью операции get() . Вот пример: auto ptr< string > pstr auto2( pstr auto.get() ); Операция release() гарантирует, что несколько указателей не являются владельцами одного и того же объекта. release() не только возвращает адрес объекта, на который ссылается auto ptr, но и передает владение им. правильно: оба указывают на один объект, но pstr auto больше не является его владельцем auto ptr< string > Предыдущий фрагмент кода нужно переписать так: pstr auto2( pstr auto.release() ); 8.4.3. Динамическое создание и уничтожение массивов Оператор new может выделить из хипа память для размещения массива. В этом случае после спецификатора типа в квадратных скобках указывается размер массива. Он может быть задан сколь угодно сложным выражением. new возвращает указатель на первый создание единственного объекта типа int с начальн значением 1024 int *pi = new int( 1024 ); создание массива из 1024 элементов элементы не инициализируются int *pia = new int[ 1024 ]; создание двумерного массива из 4x1024 элементов элемент массива. Например: int (*pia2)[ 1024 ] = new int[ 4 ][ 1024 ]; pi содержит адрес единственного элемента типа int, инициализированного значением 1024; pia - адрес первого элемента массива из 1024 элементов; pia2 - адрес начала Шаблон класса auto ptr обеспечивает значительн1е удобства и безопасность использования динамически выделяемой памяти. Однако все равно надо не терять бдительности, чтобы не навлечь на себя неприятности: нельзя инициализировать объект auto ptr указателем, полученным не с помощью оператора new, или присвоить ему такое значение. В противном случае после применения к этому объекту оператора delete поведение программы непредсказуемо; два объекта auto ptr не должны получать во владение один и тот же объект. Очевидный способ допустить такую ошибку - присвоить одно значение двум for (int index = 0; index < 1024; ++index ) присваиваются с помощью цикла for: pia[ index ] = 0; Основное преимущество динамического массива состоит в том, что количество элементов в его первом измерении не обязано быть константой, т. е. может не быть известным во время компиляции. Для массивов, определяемых в локальной или глобальной области видимости, это не так: здесь размер задавать необходимо. Например, если указатель в ходе выполнения программа: ссылается на разные С-строки, то область памяти под текущую строку обычно выделяется динамически и ее размер определяется в зависимости от длины строки. Как правило, это более эффективно, чем создавать массив фиксированного размера, способный вместить самую длинную строку: ведь все остальные строки могут быть значительно короче. Более того, программа может аварийно завершиться, если длина хотя бы одной из строк превысит отведенный лимит. Оператор new допустимо использовать для задания первого измерения массива с помощью значения, вычисляемого во время выполнения. Предположим, у нас есть const char *noerr = success ; ... const char *err189 = Error: a function declaration must следующие С-строки: specify a function return type! ; Размер создаваемого с помощью оператора new массива может быть задан значением, #include <cstring> const char *errorTxt; if (errorFound) errorTxt = errl89; else errorTxt = noerr; int dimension = strlen( errorTxt char *strl = new char[ dimension копируем текст ошибки в strl вычисляемым во время выполнения: strcpy( strl, errorTxt ); + 1; массива, содержащего чет1ре массива но 1024 элемента, т.е. pia2 адресует 4096 элементов. В общем случае массив, размещаемый в хипе, не может быть инициализирован. (В разделе 15.8 м1 покажем, как с помощью конструктора но умолчанию присвоить начальное значение динамическому массиву объектов тина класса.) Задавать инициализатор при выделении оператором new памяти под массив не разрешается. Массиву элементов встроенного тина, размещенному в хине, начальные значения / / обгчная для С++ идиома, иногда удивляющая начинающих программистов dimension разрешается заменить выражением: char *strl = new char[ str1en( errorTxt ) + 1 ]; Единица, прибавляемая к значению, которое возвращает strlen() , необходима для учета завершающего нулевого символа в C-строке. Отсутствие этой единицы - весьма распространенная ошибка, которую достаточно трудно обнаружить, поскольку она проявляет себя косвенно: происходит затирание какой-либо другой области программы. Почему? Большинство функций, которые обрабат1вают массивы, представляющие собой С-строки символов, пробегают по элементам, пока не встретят завершающий нуль. Если в конце строки нуля нет, то возможно чтение или запись в случайную область памяти. Избежать подобных проблем позволяет класс string из стандартной библиотеки С++. Отметим, что только первое измерение массива, создаваемого с помощью оператора new, может быть задано значением, вычисляемым во время выполнения. Остальные измерения int getDim(); создание двумерного массива int (*pia3)[ 1024 ] = new int[ getDim() ][ 1024 ]; правильно ошибка: второе измерение задано не константой должны задаваться константами, известными во время компиляции. Например: int **pia4 = new int[ 4 ][ getDim() ]; Оператор delete для уничтожения массива имеет следующую форму: delete[] str1; Пустые квадратные скобки необходимы. Они говорят компилятору, что указатель адресует массив, а не единичный элемент. Поскольку тип str1 - указатель на char, без этих скобок компилятор не поймет, что удалять следует целый массив. Отсутствие скобок не является синтаксической ошибкой, но правильность выполнения программы не гарантируется (это особенно справедливо для массивов, которые содержат объекте! классов, имеющих деструкторы, как это будет показано в разделе 14.4). Чтобы избежать проблем, связанных с управлением динамически выделяемой памятью для массивов, рекомендуется пользоваться контейнерными типами из стандартной библиотеки, такими, как vector, list или string. Они управляют памятью автоматически. (Тип string был представлен в разделе 3.4, тип vector - в разделе 3.10. Подробное описание контейнерных типов см. в главе 6.)
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |