Bruce Eckel - Thinking In C++. Volume 2 - Practical Programming

Здесь есть возможность читать онлайн «Bruce Eckel - Thinking In C++. Volume 2 - Practical Programming» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2003, ISBN: 2003, Издательство: Prentice Hall, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Thinking In C++. Volume 2: Practical Programming: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Thinking In C++. Volume 2: Practical Programming»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Best selling author Bruce Eckel has joined forces with Chuck Allison to write
, the sequel to the highly received and best selling
. Eckel is the master of teaching professional programmers how to quickly learn cutting edge topics in C++ that are glossed over in other C++ books. In
, the authors cover the finer points of exception handling, defensive programming and string and stream processing that every C++ programmer needs to know. Special attention is given to generic programming where the authors reveal little known techniques for effectively using the Standard Template Library. In addition, Eckel and Allison demonstrate how to apply RTTI, design patterns and concurrent programming techniques to improve the quality of industrial strength C++ applications. This book is targeted at programmers of all levels of experience who want to master C++.

Thinking In C++. Volume 2: Practical Programming — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Thinking In C++. Volume 2: Practical Programming», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

//: C01:SafeAssign.cpp

// Shows an Exception-safe operator=

#include

#include // For std::bad_alloc

#include

using namespace std;

// A class that has two pointer members using the heap

class HasPointers {

// A Handle class to hold the data

struct MyData {

const char* theString;

const int* theInts;

size_t numInts;

MyData(const char* pString, const int* pInts,

size_t nInts)

: theString(pString), theInts(pInts),

numInts(nInts) {}

} *theData; // The handle

// clone and cleanup functions

static MyData* clone(const char* otherString,

const int* otherInts, size_t nInts){

char* newChars = new char[strlen(otherString)+1];

int* newInts;

try {

newInts = new int[nInts];

} catch (bad_alloc&) {

delete [] newChars;

throw;

}

try {

// This example uses built-in types, so it won't

// throw, but for class types it could throw, so we

// use a try block for illustration. (This is the

// point of the example!)

strcpy(newChars, otherString);

for (size_t i = 0; i < nInts; ++i)

newInts[i] = otherInts[i];

} catch (...) {

delete [] newInts;

delete [] newChars;

throw;

}

return new MyData(newChars, newInts, nInts);

}

static MyData* clone(const MyData* otherData) {

return clone(otherData->theString,

otherData->theInts,

otherData->numInts);

}

static void cleanup(const MyData* theData) {

delete [] theData->theString;

delete [] theData->theInts;

delete theData;

}

public:

HasPointers(const char* someString, const int* someInts,

size_t numInts) {

theData = clone(someString, someInts, numInts);

}

HasPointers(const HasPointers& source) {

theData = clone(source.theData);

}

HasPointers& operator=(const HasPointers& rhs) {

if (this != &rhs) {

MyData* newData =

clone(rhs.theData->theString,

rhs.theData->theInts,

rhs.theData->numInts);

cleanup(theData);

theData = newData;

}

return *this;

}

~HasPointers() {

cleanup(theData);

}

friend ostream& operator<<(ostream& os,

const HasPointers& obj) {

os << obj.theData->theString << ": ";

for (size_t i = 0; i < obj.theData->numInts; ++i)

os << obj.theData->theInts[i] << ' ';

return os;

}

};

int main() {

int someNums[] = {1, 2, 3, 4};

size_t someCount = sizeof someNums / sizeof someNums[0];

int someMoreNums[] = {5, 6, 7};

size_t someMoreCount =

sizeof someMoreNums / sizeof someMoreNums[0];

HasPointers h1("Hello", someNums, someCount);

HasPointers h2("Goodbye", someMoreNums, someMoreCount);

cout << h1 << endl; // Hello: 1 2 3 4

h1 = h2;

cout << h1 << endl; // Goodbye: 5 6 7

} ///:~

For convenience, HasPointersuses the MyDataclass as a handle to the two pointers. Whenever it’s time to allocate more memory, whether during construction or assignment, the first clonefunction is ultimately called to do the job. If memory fails for the first call to the newoperator, a bad_allocexception is thrown automatically. If it happens on the second allocation (for theInts), we have to clean up the memory for theString—hence the first tryblock that catches a bad_allocexception. The second tryblock isn’t crucial here because we’re just copying ints and pointers (so no exceptions will occur), but whenever you copy objects, their assignment operators can possibly cause an exception, in which case everything needs to be cleaned up. In both exception handlers, notice that we rethrow the exception. That’s because we’re just managing resources here; the user still needs to know that something went wrong, so we let the exception propagate up the dynamic chain. Software libraries that don’t silently swallow exceptions are called exception neutral . Always strive to write libraries that are both exception safe and exception neutral. [6] If you’re interested in a more in-depth analysis of exception safety issues, the definitive reference is Herb Sutter’s Exceptional C++ , Addison-Wesley, 2000.

If you inspect the previous code closely, you’ll notice that none of the deleteoperations will throw an exception. This code actually depends on that fact. Recall that when you call deleteon an object, the object’s destructor is called. It turns out to be practically impossible, therefore, to design exception-safe code without assuming that destructors don’t throw exceptions. Don’t let destructors throw exceptions! (We’re going to remind you about this once more before this chapter is done) [7] The library function uncaught_exception( ) returns true in the middle of stack unwinding, so technically you can test uncaught_exception( ) for false and let an exception escape from a destructor. We’ve never seen a situation in which this constituted good design, however, so we only mention it in this footnote. .

Programming with exceptions

For most programmers, especially C programmers, exceptions are not available in their existing language and take a bit of adjustment. Here are some guidelines for programming with exceptions .

When to avoid exceptions

Exceptions aren’t the answer to all problems. In fact, if you simply go looking for something to pound with your new hammer, you’ll cause trouble. The following sections point out situations in which exceptions are not warranted. Probably the best advice for deciding when to use exceptions is to throw exceptions only when a function fails to meet its specification .

Not for asynchronous events

The Standard C signal( )system and any similar system handle asynchronous events: events that happen outside the flow of a program, and thus events the program cannot anticipate. You cannot use C++ exceptions to handle asynchronous events because the exception and its handler are on the same call stack. That is, exceptions rely on the dynamic chain of function calls on the program’s runtime stack (dynamic scope, if you will), whereas asynchronous events must be handled by completely separate code that is not part of the normal program flow (typically, interrupt service routines or event loops). Don’t throw exceptions from interrupt handlers .

This is not to say that asynchronous events cannot be associated with exceptions. But the interrupt handler should do its job as quickly as possible and then return. The typical way to handle this situation is to set a flag in the interrupt handler, and check it synchronously in the mainline code .

Not for benign error conditions

If you have enough information to handle an error, it’s not an exception. Take care of it in the current context rather than throwing an exception to a larger context .

Also, C++ exceptions are not thrown for machine-level events such as divide-by-zero. [8] Some compilers do throw exceptions in these cases, but they usually provide a compiler option to disable this (unusual) behavior. It’s assumed that some other mechanism, such as the operating system or hardware, deals with these events. In this way, C++ exceptions can be reasonably efficient, and their use is isolated to program-level exceptional conditions .

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

Интервал:

Закладка:

Сделать

Похожие книги на «Thinking In C++. Volume 2: Practical Programming»

Представляем Вашему вниманию похожие книги на «Thinking In C++. Volume 2: Practical Programming» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Thinking In C++. Volume 2: Practical Programming»

Обсуждение, отзывы о книге «Thinking In C++. Volume 2: Practical Programming» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x