Г. Шилтд - Самоучитель C++ (DJVU) (1114955), страница 19
Текст из файла (страница 19)
Наконец, больше нет необходимости включать в ваши программы заголовок <свЫНЬ>. В языке С при присваивании указателю возвращаемого функцией тпаИас0 значения не требуется приведение типов, поскольку тип уой1 *(тип возвращаемого функцией тейосо указателя) автоматически преобразуется в тип. (г) Глава 4.
Массивы, указатели и ссылки (п( пег рдопасс() ( гегигп 1" 3; (п( жаьп ( ) загпр +р; р = пеи аашр; УУ выделение памяти объекту гг(!р) соас « "Ошибка выделения памяти~п"; гетагп 1; г-' , †.;з( 4, Б); о ~с << "Итог равен:" «р->дег рвосг сг() << "1п"; гегигп О; 1.
Напишите программу, в которой оператор лету используется для динамического размешения переменных типа Поа1,!опя и с()аг. Задайте этим динамическим переменным значения и выведите эти значения на экран. В завершение с помощью оператора йе!е1е освободите всю динамически выделенную область памяти. 2. Создайте класс для хранения своего имени и номера телефона. Используя оператор печ, динамически выделите память для объекта этого класса и введите имя и телефон в соответствующие поля внутри объекта. 3. Какими двумя способами оператор пе1у может известить вас о неудачной по- пытке выделения памяти? 4.5. Дополнительные сведения об операторах пев и бе1е1е В этом разделе обсуждаются два дополнительных свойства операторов пеи и де!е1е. Во-первых, динамически размещаемому объекту может быть присвоено начальное значение.
Во-вторых, можно создавать динамически размещаемые массивы объектов. Вы можете присвоить динамически размещаемому объекту начальное значение, используя следующую форму оператора пек р-айаг = пем~ еурв (вачвлвнов вначегше); Самоучитлель С++ Для динамически размещаемого одномерного массива используйте такую форму оператора пеи: и-так = кем 1уре ГМве3; После выполнения этого оператора указатель р-уаг будет указывать на начальный элемент массива из я~а элементов заданного типа.
Из-за разных чисто технических причин невозможно инициализировать массив, память для которого выделена динамически. Для удаления динамически размешенного одномерного массива вам следует использовать следующую форму оператора ((е1е1е: Йе1еСе г) р-мак; При таком синтаксисе компилятор вызывает деструктор для каждого элемента массива. Это не приводит к многократному освобождению памяти по адресу, обозначенному указателем р-уаг, она освобождается только один раз. -"-фЯЩФиф49 е' Для устаревших компиляторов в операторе сне!еФе было необходимо указывать в квадратных скобках размер освобождаемого массива.
Так требовало исходное определение С++. В современных компиляторах задава ть размер массива не нужно. Примеры 4 1. В следующей программе выделяется и инициализируется память для хранения целого: О' Пример инициализации динамической переменной $1лс1цае <1овЕгеащ> из(па патезрасе в~а 'лс паап(( ( 1п1 'р; р = пеы 1кс (9)~ 1/ задание качалького значения равного 9 г~(.'р) соцс « "Сшибка выделения памяти~к"; .есцгн 1; соцл « "Это целое, на которое указывает р: " « *р « "~л" Глава 4.
Массивы, указатели и ссьаки <)е!ете р; // освобождение памяти гетцгп О) Как и следовало ожидать, программа выводит на экран число 9, являющееся начальным значением переменной, на которую указывает указатель р. 2. Следующая программа инициализирует динамически размещаемый объект: // Динамическое выделение памяти объектам ()1пс1цбе <1овцгеатп> цз1пя патезрасе згс(; с1аьв затр ( (пт1, 3; рцЬ11с: ватр(1пса, 1пт Ь) ( 1 = а; ) = Ь; (п1 цеС рго<)цсс() ( ге1пгп 1~З; ) (пт гааьп () ваптр "р( р = пеы вал'.р(б, 5); // размещение объекта с инициализацией 1=;!р) соцг « "Ошибка выделения памяти1п"; гебцгг; 1; соцг « "итог равен:'" « р->дев ргос)цсс() « "~п"т с)е1еге р; гетцгп О; При размещении объекта ваптр автоматически вызывается его конструктор, и объекту передаются значения 6 и 5, 3.
В следующей программе размещается массив целых: // Простой пример использования операторов пеи и де1ете ()1пс1ц<)е <)озггеапт> цгйпд пагпезрасе з(д; )пг гпа(п () ( (пт вр; р = пеы тпс (5]) // выделение памяти для 5 целых Самоучитель // Убедитесь, что память выделена ) ['['! р ) ! соцС « "Оюибка выделения памятиМ" гесцгп 1; 1гтт 1; аког(~.=0; 1<=; )+ — ) р[1] :ог('.— "О! '<5' ыь ) соц1 .< "Это цел 1е, па к т: рос укаэывает р)" «: < о: ' << р['1 « "1п"; Йе1есе [) р; // освобождение памяти гегцгп 0; Эта программа выводит на экран следующее: Зто целое, на которое Зто целое, на которое Зто целое, Зто целое, на которое на которое Зто целое, на которое 4.
В следующей программе создается динамический массив объектов: динамическое выделение памяти для массива объектов ()1пс1цс(е <1оз~геав> цв1пд патеврасе вгс; с1азв вашр 1пс 1~ 14 рцо11с: леус( ве1 1З (1пв а, угс Ь) ~ т = а' З 1гг де". ргос(цсс() ( гегцгп 1*3' р = пеи вашр ,'10]; // размещение массива обьектов соцс « "Ошибка выделения памяти~в"; егцгп 1; 1пг гпа1п() валер *р 1пг 1 ' указывает р[0]: О указывает р[1): 1 указывает р[2): 2 указывает р[3] . '3 указывает р !4]: 4 Глава 4. Массивы, указателии ссылки йов (1-0; 1<10; 1-+ ) р[1] .яес 17(1, 1) йох(1 0; 1<10; 1-.+) сонС « "Содерюгмое [" « 1 « "] равно:"; сопя « р[1] .дет ргоопсс( ) « "'~п"г с]е1есе [] р' тесптп О; Эта программа выводит на экран следующее: 5. Б новой версии предыдущей программы в нее вводится деструктор ва1пр и теперь при освобождении памяти, обозначенной указателем р, для каждого элемента массива вызывается деструктор: динамическое выделение памяти для массива объектов (]1пс1пс]е <1овслеал> иятпд патеярасе я й; с1аяя напр ( 1пс рпЫ1 с: "коЫ яес 11' (1пе а, тпк )о) ( 1 = а; З вЂ” ]э< »яаглр() [ сопб « "Удаление объекта...
',и"; ) 1пб де1 рког(асс ( ) ( гесптп 1*7; ) )' 1пс тпа1п ( ) яап р *р; п1 р = пех напор [10]; 1/ размещение массива объектов 11(!р) ( сопл « "Оаибка выделения памяти1п"; теептп 1; Содержимое Содержимюе Содержимое Содержимое Содержгвюе Содержимое Содержимое Содержимое Содержимое Содержгляое [О] равно: О [1] равно: 1 [2] равно." 4 [3] равно: 9 [4] равно: 1б [5] равно: 25 [б] равно: 36 [7] равно: 49 [8] равно: б4 [9] равно: 81 Самоучитель С++ 72б гог(т=О; 1<10( 1++) р(1].вег 4](з., 1); Гог (1=0) 1<10) 1++) ( сонг « "Содержимое [" «1 « ") равно:"; сонг «р[11 .дег ргос(осг() « "~п" г ) <)е]ете !.) р; гегпгп О; Эта программа выводит на экран следующее: Содержимое [0] равно: Содержгвгое [ 1 ] равно: Содержгалое [2] равно: Содержимое [3] равно: Содержимое [4] равно: Содержимое [5] равно: Содержгмое 1 6 ] равно: Содержимое [7] равно: Содержимое 8] равно: Содержимое г)1 равно: Удалениеобъекта...
Удаление объекта... Удаление объекта... Удалениеобъекта... Удаление объекта... Удаление объекта... Удаление объекта... Удаление объекта... Удалениеобъекта... Удалениеобъекта... 0 1 4 9 1б 25 Зб 49 б4 81 Как видите, деструктор вагвр вызывается десять раз — по разу на каждый элемент массива. р = ( с(таг *) гла11ос(100) // в- геру (р, "Это проверка" ) Подсказка. Строка — это просто массив символов. 1. Переделайте данную программу так, чтобы в ней использовался оператор петч. с]заг *р; Глава 4. Массивы, указатели и ссылки 2. Используя оператор пев, покажите, как динамически разместить переменную типа воиЫе и передать ей начальное значение — 123.0987, 4.6. Ссылки В С++ есть элемент, родственный указателю — это ссьика (ге/егелсе).
Ссылка является скрытым указателем и во всех случаях, и для любых целей ее можно употреблять просто как егце одно имя переменной. Ссылку допустимо использовать тремя способами. Во-первых, ссылку можно передать в функцию. Во-вторых, ссылку можно возвратить из функции. Наконец, можно создать независимую ссылку. В книге рассмотрены все эти применения ссылки, начиная со ссылки в качестве параметра функции.
Несомненно, наиболее важное применение ссылки — это передача ее в качестве параметра функции. Чтобы помочь вам разобраться в том, что такое параметр-ссылка и как он работает, начнем с программы, в которой параметром является указатель (а не ссылка): 111пс1п<1е <1овптеап~> азгпу паткеврасе вке1; уоЫ Г(1п1 *и); // использование параметра-указателя )п1 питп ( ) )пт1=0; ":|ь11 сонь « "Новое значение П " « 1 « 'п~'; те1итп Ор уоЫ Й11пь *и) *п =- 100; // занесение числа 100 в аргумент, // на который указывает указатель и Здесь функция 1() загружает целое значение 100 по адресу, который обозначен указателем п. В данной программе функция 1() вызывается из функции пи1п() с адресом переменной 1.
Таким образом, после выполнения функции 1Ц переменная 1 будет содержать число 100. В этой программе показано, как использовать указатель для реализации механизма передачи параметра посредством вызова по ссылке (са11 Ьу ге(егепсе). В программах С такой механизм является единственным спосо- Самоучитель С.ь.ь бом добиться вызова функции по ссылке. Однако в С++ с помощью параметра-ссылки можно полностью автоматизировать весь процесс. Чтобы узнать, как это сделать, изменим предыдущую программу. В ее новой версии используется параметр-ссылка: ((тпс1пс(е <1оаслеат> пяпя пагпезрасе в б; чоЫ т(ьпк ап) ) // объявление параметра-ссылки 1п(: та1п О ( 1пг 1 = 0; Г ((); сопс « "новое значение 1: " « 1 « 'М ' леепсп 0; // Теперь в функции г() используется параметр-ссылка чоЫ Г (1пс ап) ( отметьте„ что в следуюз(ей инструкнии знак * не требуется п = 100; // занесение числа 1.00 в аргумент, используемый при вызове функнии Й() Тщательно проанализируйте эту программу.
Во-первых, для объявления параметра-ссылки перед именем переменной ставится знак амперсанда (й). Таким образом, переменная п объявляется параметром функции ГЦ. Теперь, поскольку переменная п является ссылкой, больше не нужно и даже неверно указывать оператор '.
Вместо него всякий раз, когда переменная п упоминается внутри функции ГЦ, она автоматически трактуется как указатель на аргумент, используемый при вызове функции Г(). Это значит, что инструкция — 100; фактически помещает число 100 в переменную, используемую при вызове функции (Ц, каковой в данном случае является переменная 1. Далее, при вызове функции Г() перед аргументом не нужно ставить знак с<. Вместо этого, поскольку функция г() объявлена как получающая параметр-ссылку, ей автоматически передается адрес аргумента. Повторим, при использовании параметра-ссылки компилятор автоматически передает функции адрес переменной, указанной в качестве аргумента. Нет необходимости (а на самом деле и не допускается) получать адрес аргумента с помощью знака й.