Стефан Дэвис - С++ для чайников .

Тут можно читать онлайн Стефан Дэвис - С++ для чайников . - бесплатно полную версию книги (целиком) без сокращений. Жанр: sci_tech, издательство Издательский дом Вильямс. Компьютерное издательство Диалектика, год 2007. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    С++ для чайников .
  • Автор:
  • Жанр:
  • Издательство:
    Издательский дом Вильямс. Компьютерное издательство Диалектика
  • Год:
    2007
  • Город:
    Москва
  • ISBN:
    0-7645-6852-3, 978-5-8459-0723-3
  • Рейтинг:
    4/5. Голосов: 11
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Стефан Дэвис - С++ для чайников . краткое содержание

С++ для чайников . - описание и краткое содержание, автор Стефан Дэвис, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru
empty-line
1
empty-line
4

С++ для чайников . - читать онлайн бесплатно полную версию (весь текст целиком)

С++ для чайников . - читать книгу онлайн бесплатно, автор Стефан Дэвис
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

217 стр. Глава 18. Копирующий конструктор

Представим ситуацию, когда конструктор распределяет для объекта некоторые системные ресурсы, например память из кучи. Если копирующий конструктор будет выполнять простое копирование без выделения памяти из кучи для копируемого объекта, может возникнуть ситуация, когда два объекта будут считать, что именно они являются владельцами одного блока памяти. Ситуация ещё более усугубится при вызове деструкторов обоих объектов, которые попытаются освободить одну и ту же память. Взгляните на приведённый ниже пример.

/* ShallowCopy — мелкое копирование */

/* неприменимо при захвате */

/* ресурсов */

//

#include

#include

#include

#include

using namespace std ;

class Person

{

public :

Person( char *pN )

{

cout << "Конструирование \" " << pN << " \" " << endl ;

pName = new char[ strlen( pN ) + 1 ] ;

if ( pName != 0 )

{

strcpy( pName , pN ) ;

}

}

~Person( )

{

cout << "Деструкция \" " << pName << " \" " << endl ;

strcpy( pName , "Уже освобождённая память" ) ;

/* delete pName ; */

}

protected :

char *pName ;

} ;

void fn( )

{

/* Создание нового объекта */

Person p1( "Достаточно длинное имя" ) ;

/* Копирование p1 в р2 */

Person p2(p1);

}

int main( int argcs , char* pArgs[ ] )

{

setlocale ( LC_ALL , ".1251" ) ; /* печать кириллицы */

cout << "Вызов fn( )" << endl ;

fn( ) ;

cout << "Возврат из fn( )" << endl ;

/* Пауза для того, чтобы посмотреть на результат работы программы */

system( "PAUSE" ) ; return 0 ;

}

_________________

218 стр. Часть 3. Введение в классы

Эта программа порождает следующий вывод:

Вызов fn Конструирование Достаточно длинное имя Деструкция Достаточно - фото 245

Вызов fn( )

Конструирование "Достаточно длинное имя"

Деструкция "Достаточно длинное имя"

Деструкция "Уже освобождённая память"

Возврат из fn( )

Press any key to continue...

В этом примере конструктор для Person выделяет память из кучи для хранения в ней имени произвольной длины, что невозможно при использовании массивов. Деструктор возвращает эту память в кучу. Основная программа вызывает функцию fn( ) , которая создаёт объект p1 , описывающий человека, после чего создаётся копия этого объекта — р2 . Оба объекта автоматически уничтожаются при выходе из функции fn( ) .

После запуска этой программы вы получите сообщение только от одного конструктора. Это неудивительно, поскольку копия р2 создаётся с помощью предоставляемого С++ конструктора копирования по умолчанию, а он не выводит никаких сообщений. Однако, после того как p1 и р2 выходят из области видимости, вы не получите двух сообщений о ликвидации объектов, как можно было ожидать. Первый конструктор выводит ожидаемое сообщение о деструкции объекта, но второй деструктор сообщает, что память уже была освобождена.

Если бы мы действительно освобождали память в программе то программа после - фото 246

«Если бы мы действительно освобождали память в программе, то программа после попытки освободить уже освобождённую память оказалась бы в нестабильном состоянии и могла аварийно завершиться.»

[ Атас! ]

Конструктор вызывается один раз и выделяет блок памяти из кучи для хранения в нём имени человека. Копирующий конструктор, создаваемый С++, просто копирует этот адрес в новый объект, без выделения нового блока памяти.

Когда объекты ликвидируются, деструктор для р2 первым получает доступ к этому блоку памяти. Этот деструктор стирает имя и освобождает блок памяти. К тому времени как деструктор p1 получает доступ к этому блоку, память уже очищена, а имя стёрто. Теперь понятно, откуда взялось сообщение об ошибке. Суть проблемы проиллюстрирована на рис. 18.1. Объект p1 копируется в новый объект р2 , но не копируются используемые им ресурсы. Таким образом, р1 и р2 указывают на один и тот же ресурс ( в данном случае это блок памяти ). Такое явление называется "мелким" ( shallow ) копированием, поскольку при этом копируются только члены класса как таковые.

Решение этой проблемы визуально показано на рис 182 В данном случае нужен - фото 247

«Решение этой проблемы визуально показано на рис. 18.2. В данном случае нужен такой копирующий конструктор, который будет выделять ресурсы для нового объекта. Давайте добавим такой конструктор к классу и посмотрим, как он работает ( здесь приведён только фрагмент программы, полностью находящейся на прилагаемом компакт-диске ).»

[ Диск ]

class Person

{

public :

Person( char *pN )

{

cout << "Конструирование " << pN << endl ;

pName = new char[ strlen( pN ) + 1 ] ;

if ( pName != 0 )

{

strcpy( pName , pN ) ;

}

}

_________________

219 стр. Глава 18. Копирующий конструктор

/* Копирующий конструктор выделяет новый блок памяти из кучи */

Person( Person& p )

{

cout << "Копирование " << p.pName

<< " в собственный блок" << endl ;

pName = new char[ strlen( p.pName ) + 1 ] ;

if ( pName != 0 )

{

strcpy( pName , p.pName ) ;

}

}

~Person( )

{

cout << "Деструкция " << pName << endl ;

strcpy( pName , "Уже освобождённая память" ) ;

/* delete pName ; */

}

protected :

char *pName ;

} ;

Рис 181 Мелкое копирование объекта p1 в р2 Здесь копирующий конструктор - фото 248

Рис. 18.1. Мелкое копирование объекта p1 в р2

Здесь копирующий конструктор выделяет новый блок памяти для имени, а затем копирует содержимое блока памяти исходного объекта в этот новый блок ( рис. 18.2 ). Такое копирование называется " глубоким " ( deep), поскольку копирует не только элементы, но и занятые ими ресурсы ( конечно, аналогия, как говорится, притянута за уши, но ничего не поделаешь — не я придумал эти термины ).

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

Вызов fn Конструирование Достаточнодлинноеимя Копирование - фото 249

Вызов fn( )

Конструирование Достаточно_длинное_имя

Копирование Достаточно_длинное_имя в собственный блок

Деструкция Достаточно_длинное_имя

Деструкция Достаточно_длинное_имя

Возврат из fn( )

Press any key to continue...

_________________

220 стр. Часть 3. Введение в классы

Как видите, теперь указатели на строки в р1 и р2 указывают на разные данные.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Стефан Дэвис читать все книги автора по порядку

Стефан Дэвис - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




С++ для чайников . отзывы


Отзывы читателей о книге С++ для чайников ., автор: Стефан Дэвис. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x