Для программистов и опытных пользователей




Скачать 4.44 Mb.
Название Для программистов и опытных пользователей
страница 14/32
Дата публикации 20.09.2014
Размер 4.44 Mb.
Тип Документы
literature-edu.ru > Авто-обзор > Документы
1   ...   10   11   12   13   14   15   16   17   ...   32

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>



















•0

| UjnjSJ

{










„ » I

;) }эпро:гсГ}эБ<-с! » „:>

ESHBd .

ioxpjM

» ало-



















•'(5




•-• .■-. <-j

























-
















; 11U\HIpHvren кинэиэШчя is

?здишо.

'■X ujti .. » 1

ПОД

(d;)jt













J

vbS34,go ильжгвы эинэпгэШч

a //

)

.'dines

Мэн = d






















;

d¥ dines




























J






















( ) UTT3UI




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;

программа выводит на экран следующее:

Содержимое

[0]

равно:

0




Содержимое

[1]

равно :

1




Содержимое

[2]

равно:

4




Содержимое

[3]

равно:

9




Содержимое

[4]

равно:

16




Содержимое

[5]

равно:

25




Содержимое

[6]

равно :

[6




Содержимое

[7]

равно:

49




Содержимое

[8]

равно:

64




Содержимое Удаление

[9] ъекта

равно: l. . .

81




Удаление Удаление о

ъекта бъект

а. . . та. . .







Удаление объ

ъекта

1. . .







объекта...
объекта. . .

Как видите, деструктор 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().


  1. Напишите функцию neg(), которая меняет знак своего целого параметра на
    противоположный. Напишите функцию двумя способами: первый — исполь­
    зуя параметр-указатель и второй — параметр-ссылку. Составьте короткую
    программу для демонстрации обеих функций.

  2. Что неправильно в следующей программе?

// В этой программе есть ошибка #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

1   ...   10   11   12   13   14   15   16   17   ...   32

Похожие:

Для программистов и опытных пользователей icon П равила пользования услугами информационно-библиотечного центра
Правила пользования услугами информационно-библиотечного центра – документ, фиксирующий взаимоотношения пользователя с информационно-библиотечным...
Для программистов и опытных пользователей icon Ханк Рейнвотер Как пасти котов. Наставление для программистов, руководящих...
Посвящается Дэвиду, моему любимому сыну, память о тебе меня неизменно вдохновляет
Для программистов и опытных пользователей icon Дипломная работа
Степень удовлетворенности пользователей в документах по музыкальному искусству 25
Для программистов и опытных пользователей icon Задача учителя-методиста в современной школе научить созданию новых...
Созданы педагогические папки-копилки таких учителей как Ухмусултанова А. С., Нурмагомедова Н. Д., Яшувова А. М., Карамурзаева Б....
Для программистов и опытных пользователей icon Форм массовой работы
Традиционные и инновационные, серьезные и игровые формы массового формирования информационной культуры пользователей
Для программистов и опытных пользователей icon «Поддержка дистанционных олимпиад: новые идеи и технологии»
В данных тезисах рассматривается вопрос быстрого и удобного создания сайтов олимпиад с помощью типового сайта поддержки олимпиад,...
Для программистов и опытных пользователей icon Флот в первой половине XIX века Император Павел I и военно-морские силы
Поэтому флот России, пользовавшийся в конце XVIII века заслуженной славой и состоявший из опытных и смелых моряков, вместе с тем...
Для программистов и опытных пользователей icon Приказ №50/3 от 30. 08. 2013г. Анализ работы библиотеки мкоу «Трусовская...
В библиотеке образовательного учреждения художественной литературы насчитывается 3703 экземпляра, учебной 1588, электронных изданий...
Для программистов и опытных пользователей icon Реферат Дипломный проект посвящен модернизации локальной сети организации «Надежный Контакт»
Проанализирован список задач решаемых с помощью локальной сети; также были изучены аппаратные и программные средства, необходимые...
Для программистов и опытных пользователей icon Курсовая работа студента 342 группы Матвеева Н. Н. «Реализация отмены/повтора...
Средств разработчиков и проектировщиков по можно отдельно выделить так называемые case-средства (case computer-Aided Software Engineering)....
Литература


При копировании материала укажите ссылку © 2015
контакты
literature-edu.ru
Поиск на сайте

Главная страница  Литература  Доклады  Рефераты  Курсовая работа  Лекции