» » » Д. Стефенс - C++. Сборник рецептов


Авторские права

Д. Стефенс - C++. Сборник рецептов

Здесь можно скачать бесплатно "Д. Стефенс - C++. Сборник рецептов" в формате fb2, epub, txt, doc, pdf. Жанр: Программирование, издательство КУДИЦ-ПРЕСС, год 2007. Так же Вы можете читать книгу онлайн без регистрации и SMS на сайте LibFox.Ru (ЛибФокс) или прочесть описание и ознакомиться с отзывами.
Д. Стефенс - C++. Сборник рецептов
Рейтинг:
Название:
C++. Сборник рецептов
Автор:
Издательство:
КУДИЦ-ПРЕСС
Год:
2007
ISBN:
5-91136-030-6
Скачать:

99Пожалуйста дождитесь своей очереди, идёт подготовка вашей ссылки для скачивания...

Скачивание начинается... Если скачивание не началось автоматически, пожалуйста нажмите на эту ссылку.

Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.

Как получить книгу?
Оплатили, но не знаете что делать дальше? Инструкция.

Описание книги "C++. Сборник рецептов"

Описание и краткое содержание "C++. Сборник рецептов" читать бесплатно онлайн.



Данная книга написана экспертами по C++ и содержит готовые рецепты решения каждодневных задач для программистов на С++. Один из авторов является создателем библиотеки Boost Iostreams и нескольких других библиотек C++ с открытым исходным кодом. В книге затрагивается множество тем, вот лишь некоторые из них: работа с датой и временем; потоковый ввод/вывод; обработка исключений; работа с классами и объектами; сборка приложений; синтаксический анализ XML-документов; программирование математических задач. Читатель сможет использовать готовые решения, а сэкономленное время и усилия направить на решение конкретных задач.






Кроме перемещения операторов инициализации членов в список инициализации пример 9.3 отличается от примера 9.2 еще одним свойством. Объекты-члены Device на этот раз не создаются в динамической памяти с помощью оператора new. Я сделал это для иллюстрации двух особенностей, связанных с безопасностью и применением объектов-членов.

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

Но, возможно, вам требуется иметь члены, использующие динамическую память (или с ними вы предпочитаете иметь дело). Рассмотрим подход, используемый в первоначальном классе Broker в примере 9.2. Вы можете просто инициализировать ваши указатели в списке инициализации, не так ли?

class BrokerBad {

public:

 BrokerBad(int devno1, int devno2)

  try : dev1_(new Device(devno1)), // Создать объекты динамической

   dev2_(new Device(devno2)) {}    // памяти в списке инициализации

  catch (...) {

   if (dev1_) {

    delete dev1_; // He должно компилироваться и

    delete dev2_; // является плохим решением, если

   }              // все же будет откомпилировано

   throw; // Повторное выбрасывание того же самого исключения

  }

 ~BrokerBad() {

  delete dev1_;

  delete dev2_;

 }

private:

 BrokerBad();

 Device* dev1_;

 Device* dev2_;

};

Нет, так делать нельзя. Здесь две проблемы. Прежде всего, это не допустит ваш компилятор, потому что расположенный в конструкторе блок catch не должен позволить программному коду получить доступ к переменным-членам, так как их еще нет. Во-вторых, даже если ваш компилятор позволяет это делать, это будет плохим решением. Рассмотрим ситуацию, когда при конструировании объекта dev1_ выбрасывается исключение. Ниже дается программный код, который будет выполняться в catch-обработчике.

catch (...) {

 if (dev1_) { // Какое значение имеет эта переменная?

  delete dev1_; // в данном случае вы удаляете неопределенное значение

  delete dev2_;

 }

 throw; // Повторное выбрасывание того же самого исключения

}

Если исключение выбрасывается в ходе конструирования dev1_, то оператором new не может быть возвращен адрес нового выделенного участка памяти и значение dev1_ не меняется. Тогда что эта переменная содержит? Она будет иметь неопределённое значение, так как она никогда не инициализировалась. В результате, когда вы станете выполнять оператор delete dev1_, вы, вероятно, попытаетесь удалить объект, используя недостоверный адрес, что приведет к краху программы, вы будете уволены, и вам придется жить с этим позором всю оставшуюся жизнь.

Чтобы избежать такое фиаско, круто изменяющее вашу жизнь, инициализируйте в списке инициализации ваши указатели значением NULL и затем создавайте в конструкторе объекты, использующие динамическую память. В этом случае будет легче перехватывать любую исключительную ситуацию и выполнять подчистку, поскольку допускается использовать оператор delete для NULL-указателей.

BrokerBetter(int devno1, int devno2) :

 dev1_(NULL), dev2_(NULL) {

  try {

   dev1_ = new Device(devno1);

   dev2_ = new Device(devno2);

  } catch (...) {

   delete dev1_; // Это сработает в любом случае

   throw;

  }

 }

Итак, вышесказанное можно подытожить следующим образом: если вам необходимо использовать члены-указатели, инициализируйте их значением NULL в списке инициализации и затем выделяйте в конструкторе память для соответствующих объектов, используя блок try/catch. Вы можете освободить любую память в catch-обработчике. Однако, если допускается работа с автоматическими членами, сконструируйте их в списке инициализации и используйте специальный синтаксис блока try/catch для обработки любых исключений.

Смотри также

Рецепт 9.2.

9.4. Создание безопасных при исключениях функций-членов

Проблема

Создается функция-член и необходимо обеспечить базовые и строгие гарантии ее безопасности при исключениях, а именно отсутствие утечки ресурсов и то, что объект не будет иметь недопустимое состояние в том случае, если выбрасывается исключение.

Решение

Необходимо выяснить, какие операции могут выбрасывать исключения, и следует выполнить их первыми, обычно заключая в блок try/catch. После того как будет выполнен программный код, который может выбрасывать исключение, вы можете изменять состояние объектов. В примере 9.4 показан один из способов обеспечения безопасности функции-члена при исключениях.

Пример 9.4. Безопасная при исключениях функция-член

class Message {

public:

 Message(int bufSize = DEFAULT_BUF_SIZE) :

  bufSize_(bufSize), initBufSize_(bufSize), msgSize_(0), buf_(NULL) {

  buf_ = new char[bufSize];

 }

 ~Message() {

  delete[] buf_;

 }


 // Добавить в конец символьные данные

 void appendData(int len, const char* data) {

  if (msgSize_+len > MAX_SIZE) {

   throw out_of_range("Data size exceeds maximum size.");

  }

  if (msgSize_+len > bufSize_) {

   int newBufSize = bufSize_;

   while ((newBufSize *= 2) < msgSize_+len);

   char* p = new char[newBufSize]; // Выделить память

                                   // для нового буфера

   copy(buf_, buf_+msgSize_, p);     // Скопировать старые данные

   copy(data, data+len, p+msgSize_); // Скопировать новые данные

   msgSize_ += len;

   bufSize_ = newBufSize;

   delete[] buf_; // Освободись старый буфер и установить указатель на

   buf_ = p;      // новый буфер

  } else {

   copy(data, data+len, buf_+msgSize_);

   msgSize_ += len;

  }

 }


 // Скопировать данные в буфер вызывающей программы

 int getData(int maxLen, char* data) {

  if (maxLen < msgSize_) {

   throw out_of_range("This data is too big for your buffer.");

  }

  copy(buf_, buf_+msgSize_, data);

  return(msgSize_);

 }


private:

 Message(const Message& orig) {}           // Мы рассмотрим эти операторы

 Message& operator=(const Message& rhs) {} // в рецепте 9.5

 int bufSize_;

 int initBufSize_;

 int msgSize_;

 char* buf_;

};

Обсуждение

Представленный в примере 9.4 класс Message является классом, содержащим символьные данные; вы могли бы использовать его в качестве оболочки текстовых или бинарных данных, которые передаются из одной системы в другую. Здесь нас интересует функция-член appendData, которая добавляет данные, переданные вызывающей программой, в конец данных, уже находящихся в буфере, причем увеличивая при необходимости размер буфера. Здесь обеспечивается строгая гарантия безопасности этой функции-члена при исключениях, хотя на первый взгляд может быть не совсем понятно, чем это достигается.

Рассмотрим следующий фрагмент appendData.

if (msgSize_+len > bufSize_) {

 int newBufSize = bufSize_;

 while ((newBufSize *= 2) < msgSize_+len);

 char* p = new char[newBufSize];

Этот блок программного кода обеспечивает увеличение размера буфера. Я его увеличиваю путем удвоения его размера до тех пор, пока он не станет достаточно большим. Этот фрагмент программного кода безопасен, потому что исключение может быть выброшено здесь только при выполнении оператора new, и я не обновляю состояние объекта и не выделяю память ни под какие другие ресурсы до завершения его выполнения. Этот оператор выбросит исключение bad_alloc, если операционная система не сможет выделить участок памяти необходимого размера.

После успешного распределения памяти я могу начать обновление состояния объекта, копируя данные и обновляя значения переменных-членов.

copy(buf_, buf_+msgSize_, p);

copy(data, data+len, p+msgSize_);

msgSize_ += len;

bufSize_ = newBufSize;

delete[] buf_;

buf_ = p;

Ни одна из этих операций не может выбросить исключение, поэтому нам не о чем волноваться. (Это происходит только из-за того, что буфер представляет собой последовательность символов; дополнительные разъяснения вы найдете при обсуждении примера 9.5.)


На Facebook В Твиттере В Instagram В Одноклассниках Мы Вконтакте
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!

Похожие книги на "C++. Сборник рецептов"

Книги похожие на "C++. Сборник рецептов" читать онлайн или скачать бесплатно полные версии.


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

Все книги автора Д. Стефенс

Д. Стефенс - все книги автора в одном месте на сайте онлайн библиотеки LibFox.

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Отзывы о "Д. Стефенс - C++. Сборник рецептов"

Отзывы читателей о книге "C++. Сборник рецептов", комментарии и мнения людей о произведении.

А что Вы думаете о книге? Оставьте Ваш отзыв.