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», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

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

Интервал:

Закладка:

Сделать

delete [] bp; // Array delete

delete op;

}

};

int main() {

try {

UseResources ur(3);

} catch(int) {

cout << "inside handler" << endl;

}

} ///:~

The output is the following: .

UseResources()

Cat()

Cat()

Cat()

allocating a Dog

inside handler

The UseResourcesconstructor is entered, and the Catconstructor is successfully completed for the three array objects. However, inside Dog::operator new( ), an exception is thrown (to simulate an out-of-memory error). Suddenly, you end up inside the handler, without the UseResourcesdestructor being called. This is correct because the UseResourcesconstructor was unable to finish, but it also means the Catobjects that were successfully created on the heap were never destroyed .

Making everything an object

To prevent such resource leaks, you must guard against these "raw" resource allocations in one of two ways:

· You can catch exceptions inside the constructor and then release the resource.

· You can place the allocations inside an object’s constructor, and you can place the deallocations inside an object’s destructor.

Using the latter approach, each allocation becomes atomic, by virtue of being part of the lifetime of a local object, and if it fails, the other resource allocation objects are properly cleaned up during stack unwinding. This technique is called Resource Acquisition Is Initialization (RAII for short) , because it equates resource control with object lifetime. Using templates is an excellent way to modify the previous example to achieve this: .

//: C01:Wrapped.cpp

// Safe, atomic pointers

#include

using namespace std;

// Simplified. Yours may have other arguments.

template class PWrap {

T* ptr;

public:

class RangeError {}; // Exception class

PWrap() {

ptr = new T[sz];

cout << "PWrap constructor" << endl;

}

~PWrap() {

delete [] ptr;

cout << "PWrap destructor" << endl;

}

T& operator[](int i) throw(RangeError) {

if(i >= 0 && i < sz) return ptr[i];

throw RangeError();

}

};

class Cat {

public:

Cat() { cout << "Cat()" << endl; }

~Cat() { cout << "~Cat()" << endl; }

void g() {}

};

class Dog {

public:

void* operator new[](size_t) {

cout << "Allocating a Dog" << endl;

throw 47;

}

void operator delete[](void* p) {

cout << "Deallocating a Dog" << endl;

::operator delete[](p);

}

};

class UseResources {

PWrap cats;

PWrap dog;

public:

UseResources() {

cout << "UseResources()" << endl;

}

~UseResources() {

cout << "~UseResources()" << endl;

}

void f() { cats[1].g(); }

};

int main() {

try {

UseResources ur;

} catch(int) {

cout << "inside handler" << endl;

} catch(...) {

cout << "inside catch(...)" << endl;

}

} ///:~

The difference is the use of the template to wrap the pointers and make them into objects. The constructors for these objects are called before the body of the UseResourcesconstructor, and any of these constructors that complete before an exception is thrown will have their associated destructors called during stack unwinding .

The PWraptemplate shows a more typical use of exceptions than you’ve seen so far: A nested class called RangeErroris created to use in operator[ ]if its argument is out of range. Because operator[ ]returns a reference, it cannot return zero. (There are no null references.) This is a true exceptional condition—you don’t know what to do in the current context, and you can’t return an improbable value. In this example, RangeErroris simple and assumes all the necessary information is in the class name, but you might also want to add a member that contains the value of the index, if that is useful .

Now the output is: .

Cat()

Cat()

Cat()

PWrap constructor

allocating a Dog

~Cat()

~Cat()

~Cat()

PWrap destructor

inside handler

Again, the storage allocation for Dogthrows an exception, but this time the array of Catobjects is properly cleaned up, so there is no memory leak .

auto_ptr

Since dynamic memory is the most frequent resource used in a typical C++ program, the standard provides an RAII wrapper for pointers to heap memory that automatically frees the memory. The auto_ptrclass template, defined in the header, has a constructor that takes a pointer to its generic type (whatever you use in your code). The auto_ptrclass template also overloads the pointer operators *and ->to forward these operations to the original pointer the auto_ptrobject is holding. You can, therefore, use the auto_ptrobject as if it were a raw pointer. Here’s how it works: .

//: C01:Auto_ptr.cpp

// Illustrates the RAII nature of auto_ptr

#include

#include

using namespace std;

class TraceHeap {

int i;

public:

static void* operator new(size_t siz) {

void* p = ::operator new(siz);

cout << "Allocating TraceHeap object on the heap "

<< "at address " << p << endl;

return p;

}

static void operator delete(void* p) {

cout << "Deleting TraceHeap object at address "

<< p << endl;

::operator delete(p);

}

TraceHeap(int i) : i(i) {}

int getVal() const {

return i;

}

};

int main() {

auto_ptr pMyObject(new TraceHeap(5));

cout << pMyObject->getVal() << endl; // prints 5

} ///:~

The TraceHeapclass overloads the operator newand operator deleteso you can see exactly what’s happening. Notice that, like any other class template, you specify the type you’re going to use in a template parameter. You don’t say TraceHeap*, however; auto_ptralready knows that it will be storing a pointer to your type. The second line of main( )verifies that auto_ptr’s operator->( )function applies the indirection to the original, underlying pointer. Most important, even though we didn’t explicitly delete the original pointer (in fact we can’t here, since we didn’t save its address in a variable anywhere), pMyObject’s destructor deletes the original pointer during stack unwinding, as the following output verifies: .

Allocating TraceHeap object on the heap at address 8930040

5

Deleting TraceHeap object at address 8930040

The auto_ptrclass template is also handy for pointer data members. Since class objects contained by value are always destructed, auto_ptrmembers always delete the raw pointer they wrap when the containing object is destructed [5] For more detail on auto_ptr , see Herb Sutter’s article entitled, "Using auto_ptr Effectively" in the October 1999 issue of the C/C++ Users Journal , pp. 63–67. .

Function-level try blocks

Since constructors can routinely throw exceptions, you might want to handle exceptions that occur when an object’s member or base subobjects are initialized. To do this, you can place the initialization of such subobjects in a function-level try block . In a departure from the usual syntax, the tryblock for constructor initializers is the constructor body, and the associated catchblock follows the body of the constructor, as in the following example .

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

Интервал:

Закладка:

Сделать

Похожие книги на «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