Скачать 4.44 Mb.
|
int main() { int *p; p = new int; // выделение памяти для целого Ш !р) cout « "Ошибка выделения памяти\n"; return 1; i *р = 1000; cout « "Это целое, на которое указывает р: *р « "\п"; delete p; // освобождение памяти return 0; Обратите внимание, что возвращаемое оператором new значение перед использованием проверяется. Как уже упоминалось, эта проверка имеет значение только в том случае, если в вашем компиляторе при неудачной попытке выделения памяти оператор new возвращает нулевой указатель. 2. Пример, в котором память объекту выделяется // Динамическое выделение памяти объектам #include using namespace std; class samp { inti,j ; public: void set_ij (int a, int b) { i = a; j = b; } :луэи BdoiBdano Лис1оф оьСтетЛй'экэ кЛечконэи ' -вне эончквьвн Лхяэчдо Аиоиэв1пэиев(1 ияээышвний' чхиояэи(1п эхэжои ■яохяэчдо няиээви эгшэвПхэи -EBd ияээьиивний' чхвявееоэ онжои 'xiqdoxa-oa 'эинэьвне эончквьвн онэояэ -ndu чхнд хэжои Лхяэчдо AwowaBlnawEBd ияээышвний' 'XHadau-og 'э и мэн aodoxBdauo вяхэиояэ хннчкэхинконой' внй кэхшвйжАэдо SKatfEBd иохе и ллэи xedoxedauo 90 ЭЯХ1ЧН -он ионьвй'Аэн о эвя чхихээяеи хэжои Avau doxBdauo иивдоэонэ кмАяй': Kirou эиПютАяхэхэяхооэ я нофэкэх и кми эхй/ -эяя и вээвкя шохе вхяэчдо mfif чхкмвн эхикэйчя ияээышвний 'жэи doxBdauo •внофэкэх BdawoH и инэии охэояэ KHHSHBdx Kirtf ээвкя эхив№оэ •ихкмвн чхэвкдо етАннэкэйчя ияээышвний шэя ашИодояэо э;э{эр BdoxBdauo шчПкжон о 3HH3mdaHBE g 'HBdse вн кинэьвне ихе эхи^зяня и винэьвне WHHHawadau иияэ -эьиивний' иихе axHBli'Bg 'ящз и §но[ ';воц вних xi4HH3W3dau BHHalnawEBd шояэ кйг' кэхэАечконэи мэи doxBdauo Hodoxos я 'AwwBdiodu эхишиивн mm, -■'■ ■■■■ ■ :-.- -:: .. ■ :" L>
M и»шяээ и и1/Э1еее»Л 'паиоое^ -р eaei/j 122 Самоучитель C++ динамически размещаемого одномерного массива используйте такую форму оператора new: p-var = new type [size]; После выполнения этого оператора указатель p-var будет указывать на начальный элемент массива из size элементов заданного типа. Из-за разных чисто технических причин невозможно инициализировать массив, которого выделена, удаления динамически размешенного одномерного массива вам следует использовать следующую форму оператора delete: delete [] p-var; При таком синтаксисе компилятор вызывает деструктор для каждого элемента массива. Это не приводит к многократному освобождению памяти по адресу, обозначенному указателем p-var, она освобождается только один раз. ■ 'I ■ -У- Для \ х компиляторов в операторе delete было необходимо указы- вать в квадратных скобках размер освобождаемого массива. Так требовало исходное определение C++. В современных компиляторах задавать размер массива не нужно. i Примеры J 1. В следующей программе выделяется и инициализируется память для хранения целого: // Пример инициализации динамической переменной #include using namespace std; int mainO) { int *p; p = new .: Э} ; // задание начального значения равного 9 cout « "Ошибка выделения памяти\п"; return 1; J cout « : "Это целое, на которое указывает р: 4. Массивы, указатели и ссылки 123 delete p; // освобождение return 0; Как и следовало ожидать, программа выводит на экран число 9, [ значением переменной, на которую указывает указатель р. 2. Следующая программа инициализирует динамически размещаемый объект: // Динамическое выделение памяти объектам #include using namespace std; class samp { int i, j; public: samp fint a, int b) { i = a; j = b; } int get_product(} { return i*j; } J; int main (} ( samp *p; p = new samp (6, 5); // размещение объекта с инициализацией cout « "Ошибка выделения памяти\п"; return 1; } cout « "Итог равен: delete p; return 0; При размещении объекта samp автоматически вызывается его конструктор, и объекту передаются значения 6 и 5, 3. В следующей программе размещается массив целых: // Простой пример использования операторов new и delete #include using namespace std; int main () { int *p; p = new int [5]; // выделение памяти для 5 целых 124 C++ I/ iff!p) ! cout << ' return 1; что память памяти\п" ; int i ; for(i=0 ; i for(i=0; i<5; i cout « "2 cout « p[i] « "\n"; p[" « i « "]: "; delete [] p; // освобождение return 0; Эта программа на экран Это целое, на которое указывает р [ С : О Это целое, на которое указывает р[ : 1 Это целое, на которое указывает .. 2 Это целое, на которое указывает р[ ! 3 Это целое, на которое указывает ; : 4 4. В следующей программе создается массив объектов: // Динамическое выделение памяти ^include using namespace std; массива объектов class samp ( int i, j ; public: void set_ij(int a, int b) f i = a; j = b; } int get_product() { return i*j; } I; int main() ( samp *p; int i ; p = new samp [10]; // размещение массива объектов if(!p) { cout «"Ошибка выделения памяти\n"; return 1; 4. Массивы, указатели и ссылки 125 for(i-0; for(i=0; i<10; i++) ( cout « "Содержимое < i « cout «p[i] .get_product ( ) « "\n"; j delete [] p; return 0; Эта программа выводит на экран Содержимое Содержимое Содержимое Содержимое Содержимое Содержимое Содержимое I01 [1] [2] [3] Ш [5] гб1 [8] [9] равно: О равно: 1 равно: 4 равно: 9 равно: 16 равно: 2 5 равно: 3 6 равно: 49 равно: 64 равно: 81 5 . В новой версии теперь при освобождении программы в нее вводится деструктор samp и , обозначенной указателем р, для каждого // Динамическое выделение памяти для массива ^include using namespace std; class samp { int i, j ; public: void set_ij (int a, int b) { i = a; j - b; } -sampO { cout « "Удаление объекта ... \n"; } int get_product ( ) { return i* j ; } it int main ( ) i samp *p; int i ; p = new samp [10]; // размещение массива объектов if(!p) ! cout « "Ошибка выделения памяти\п"; return 1; 726 Самоучитель C++ for{i=0; .*at_ij [i, i); for(i=0; i cout « "Содержимое [" « i « "] равно:"; cout « p[i] .get_product(} « "\n"; } delete [J p; return 0; программа выводит на экран следующее:
объекта... объекта. . . Как видите, деструктор samp вызывается десять раз — по разу на массива. в ней использовался оператор new. 1. Переделайте данную программу так, char *p; р - ( char *) rnalloc(lOO) ; // ... s t r cpy i p, "Это проверка"); Подсказка. Строка — это просто массив символов. Глава 4. Массивы, указатели и ссылки 127 2. Используя оператор new, покажите, как динамически разместить переменную типа double и передать ей начальное значение — 123.0987. 4.6. Ссылки В C++ есть элемент, родственный указателю — это ссылка (reference). Ссылка является скрытым указателем и во всех случаях, и для любых целей ее можно употреблять просто как еще одно имя переменной. Ссылку допустимо использовать тремя способами. Во-первых, ссылку можно передать в функцию. Во-вторых, ссылку можно возвратить из функции. Наконец, можно создать независимую ссылку. В книге рассмотрены все эти применения ссылки, начиная со ссылки в качестве параметра функции. Несомненно, наиболее важное применение ссылки это передача ее в качестве параметра функции. Чтобы помочь вам разобраться в том, что такое параметр -ссылка и как он работает, начнем с программы, в которой параметром является указатель (а не ссылка): ^include using namespace std; void f(int *n) ; // использование параметра-указателя int main ( ) [ int i = 0; cout « "Новое значение i: " « i « 'nV; return 0 ; void f(int *n) *n = 100; // занесение числа 100 в аргумент, // на который указывает указатель п () загружает целое значение 100 по адресу, который обозна-указателем п. В данной программе функция f() вызывается из функции шлш() с адресом переменной L Таким образом, после выполнения функции f() переменная i будет содержать число 100. В этой программе показано, как использовать указатель для реализации механизма передачи параметра посредством вызова по ссылке (call by reference). В программах С такой механизм является единственным спосо- Самоучитель C++ бом добиться вызова функции по ссылке. Однако в C++ с помощью пара-сылки можно полностью автоматизировать весь процесс. Чтобы уз-ь, как это сделать, изменим предыдущую программу. В ее новой версии используется параметр-ссылка: ^include using namespace std; void f(int &n) ; // объявление параметра- int main() I int i 0; cout « ■ "Новое значение i: < i « return 0; // Теперь в функции f ( ) используется параметр-ссылка void f(int &n) // отметьте, что в следующей инструкции знак * не требуется п = 100; // занесение числа 100 в аргумент, // используемый при вызове функции f {) проанализируйте эту программу. Во-первых, для объявления параметра-ссылки перед именем переменной ставится знак амперсанда (&). Таким образом, переменная п объявляется параметром функции f(). Теперь, поскольку переменная п является ссылкой, больше не нужно и даже неверно указывать оператор *. Вместо него всякий раз, когда переменная п упоминается внутри функции f(), она автоматически трактуется как указатель на аргумент, используемый при вызове функции f(). Это значит, что инструкция л - 100; фактически помещает число 100 в переменную, используемую при вызове функции f(), каковой в данном случае является переменная L Далее, при вызове функции f() перед аргументом не нужно ставить знак &. Вместо этого, поскольку функция f() объявлена как получающаяпар ей автоматически передается адрес аргумента. Повторим, при использовании параметра-ссылки компилятор ски передает функции адрес переменной, указанной в качестве аргумента. Нет необходимости (а на самом деле и не допускается) получать адрес аргу-с помощью знака &. Более того, внутри функции компилятор автома- 4. Массивы, указатели и ссылки _ 129 тически использует переменную, на которую указывает параметр-ссылка, Нет необходимости (и опять не допускается) ставить знак *. Таким образом, параметр -ссылка полностью автоматизирует механизм передачи параметра посредством вызова функции по ссылке. Важно понимать следующее: адрес, на который указывает ссылка, вы изменить не можете. Например, если в предыдущей программе инструкция &++■; находилась бы внутри функции f(), ссылка п по-прежнему указывала бы на переменную i в функции main(). Вместо инкрементирования адреса, на который указывает ссылка п, эта инструкция инкрементирует значение пере-(в данном случае это переменная i). имеют несколько преимуществ по сравнению с гичными (более или менее) альтернативными параметрами-указателями. Во-первых, с практической точки зрения нет необходимости получать и передавать в функцию адрес аргумента. При использовании параметра-ссылки адрес передается автоматически. Во-вторых, по мнению многих программистов, параметры-ссылки предлагают более понятный и элегантный интерфейс, чем неуклюжий механизм указателей. В-третьих, как вы в следующем разделе, при передаче объекта функции через ссылку объекта не создается. Это уменьшает вероятность ошибок, связанных с построением копии аргумента и вызовом ее деструктора. Классическим примером передачи аргументов по ссылке является функция, меняющая местами значения двух своих аргументов. В данном примере в функции swapargs() ссылки используются для того, чтобы два ее целых аргумента: ^include using namespace std; void swapargs(int &x, int £y); int main () i int i, j; i = 10; j = 19; cout « "i: " « i « ", "; cout « "j : " « j « "\n"; swapargs(i, j) ; 730 Самоучитель C+ + cout « "После перестановки: "; cout « "i: " « i « ", "; cout « "j : " « j « "\n"; return 0 ; } void swapargs(int &x, int &y} { int t; t = x; x =y; у = t; ) Если бы при написании функции swapargsQ вместо ссылок использовались указатели, то функция выглядела бы следующим образом: void swapargsfint *x, int *y) ! int t; t — . Ч1„ *х = *у; *у = t; Как видите, благодаря использованию ссылок в функции swapargs(), необходимость указывать знак *. 2. В следующей программе с помощью функции round() округляется значение типа double. Округляемое значение передается по ссылке. ^include ^include using namespace std; void round (double #) ; int main ( ) iouble i = 100.4; :>ut « i « "после округления "; l ut « i « "\n"; л = 10.9; cout « i « "после округления round(i ) ; cout « i « "\n"; Глава 4. Массивы, return 0; указатели ссылки 131 void round (double snum) { double frac; double val; // разложение num на целую и дробную frac =modf(num, &val); . if ffrac < 0.5) num = val; else num = val + 1.0; В функции roun (10 для разложения числа на целую и дробную части указана редко используемая функция modf(). Возвращаемым значением этой функции является дробная часть; целая часть помещается в переменную, на которую указывает второй параметр функции modf().
// В этой программе есть ошибка #include using namespace std; void triple(double Snum) int main() { double d = 7.0; tripleUd); cout « d; return 0; ft void triple(double Snum} 132 Самоучитель C++ num = 3 * num; 3. Перечислите преимущества параметров-ссылок. 4.7. Передача ссылок на объекты Как вы узнали из главы 3, если объект передается функции по значению, то в функции создается его копия. Хотя конструктор копии не вызывается, при возвращении функцией своего значения вызывается деструктор копии. Повторный вызов деструктора может привести в некоторых случаях к серьезным проблемам (например, при освобождении деструктором ской Решает эту проблему передача объекта по ссылке. (Другое решение, о котором будет рассказано в главе 5, подразумевает использование конструктора копий.) При этом копия объекта не создается, и поэтому при возвращении функцией своего значения деструктор не вызывается. Тем не менее, запомните: изменения объекта внутри функции влияют на исходный объект, указанный в качестве аргумента функции. важно понимать, что ссылка не указатель, хотя она и указывает на адрес объекта. Поэтому при передаче объекта по ссылке для доступа к его 1 используется оператор точка (.), а не стрелка (->}. 1. В следующем примере на экран выводится значение, передаваемое по ссылке, но сначала рассмотрим версию программы, в которой объект типа myclass() передается в функцию f() по значению: ^include using namespace std; class myclass { int who ; public: myclass(int n) ( who = n; cout « "Работа конструктора " « who |
П равила пользования услугами информационно-библиотечного центра Правила пользования услугами информационно-библиотечного центра – документ, фиксирующий взаимоотношения пользователя с информационно-библиотечным... |
Ханк Рейнвотер Как пасти котов. Наставление для программистов, руководящих... Посвящается Дэвиду, моему любимому сыну, память о тебе меня неизменно вдохновляет |
||
Дипломная работа Степень удовлетворенности пользователей в документах по музыкальному искусству 25 |
Задача учителя-методиста в современной школе научить созданию новых... Созданы педагогические папки-копилки таких учителей как Ухмусултанова А. С., Нурмагомедова Н. Д., Яшувова А. М., Карамурзаева Б.... |
||
Форм массовой работы Традиционные и инновационные, серьезные и игровые формы массового формирования информационной культуры пользователей |
«Поддержка дистанционных олимпиад: новые идеи и технологии» В данных тезисах рассматривается вопрос быстрого и удобного создания сайтов олимпиад с помощью типового сайта поддержки олимпиад,... |
||
Флот в первой половине XIX века Император Павел I и военно-морские силы Поэтому флот России, пользовавшийся в конце XVIII века заслуженной славой и состоявший из опытных и смелых моряков, вместе с тем... |
Приказ №50/3 от 30. 08. 2013г. Анализ работы библиотеки мкоу «Трусовская... В библиотеке образовательного учреждения художественной литературы насчитывается 3703 экземпляра, учебной 1588, электронных изданий... |
||
Реферат Дипломный проект посвящен модернизации локальной сети организации «Надежный Контакт» Проанализирован список задач решаемых с помощью локальной сети; также были изучены аппаратные и программные средства, необходимые... |
Курсовая работа студента 342 группы Матвеева Н. Н. «Реализация отмены/повтора... Средств разработчиков и проектировщиков по можно отдельно выделить так называемые case-средства (case computer-Aided Software Engineering).... |
Поиск на сайте Главная страница Литература Доклады Рефераты Курсовая работа Лекции |