Читаем Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ полностью

// размещающие new/delete

static void *operator new(std::size_t size, void *ptr) throw(bad_alloc)

{ return ::operator new(size, ptr);}

static void operator delete(void *pMemory, void *ptr) throw

{ ::operator delete(pMemory, ptr);}

// не возбуждающие исключений new/delete

static void *operator new(std::size_t, const std::nothrow_t nt) throw

{ return ::operator new(size, nt)}

static void operator delete(void *pMemory, const std::nothrow_t) throw

{ ::operator delete(pMemory, nt);}

};


Пользователи, которые хотят пополнить свой арсенал специальными формами new, применяют наследование и using-объявления (см. правило 33), чтобы получить доступ к стандартным формам:


class Widget: public StandardNewDeleteForms { // наследование

public: // стандартных форм

using StandardNewDeleteForms::operator new; // сделать эти формы

using StandardNewDeleteForms::operator delete; // видимыми

static void *operator new(std::size_t size, // добавляется

std::ostream logStream) // специальный

throw(bad_alloc); // размещающий new

static void operator delete(void *pMemory, // добавляется

std::ostream logStream) // соответствующий

throw; // размещающий delete

...

};


Что следует помнить

• Когда вы пишете размещающую версию оператора new, убедитесь, что не забыли о соответственном размещающем операторе delete. Если его не будет, то в вашей программе могут возникать тонкие, трудноуловимые утечки памяти.

• Объявляя размещающие версии new и delete, позаботьтесь о том, чтобы нечаянно не скрыть нормальных версий этих функций.

Глава 9

Разное

Несмотря на то что эта глава состоит всего из трех правил, все они очень важны.

В первом правиле подчеркивается, что предупреждения компилятора – не пустяк, на который можно не обращать внимания. По крайней мере, если вы хотите, чтобы ваши программы вели себя правильно. Во втором представлен обзор стандартной библиотеки C++, включая и новую функциональность, предложенную в отчете TR1. И наконец, в последнем правиле представлен обзор проекта Boost – возможно, наиболее важного Web-сайта, посвященного общим вопросам применения C++. Игнорируя советы, изложенные в этих правилах, писать эффективные программы на C++ как минимум нелегко.

Правило 53: Обращайте внимание на предупреждения компилятора

Многие программисты зачастую игнорируют предупреждения компилятора. В конце концов, если бы проблема была по-настоящему серьезной, компилятор выдал бы ошибку! Подобные рассуждения могут быть сравнительно безвредными при работе с какими-нибудь другими языками, но в отношении C++ можно поручиться, что создатели компиляторов точнее вас оценивают истинное положение дел. Например, ниже приведена ошибка, которую рано или поздно допускает каждый из нас:


class B {

public:

virtual void f const;

};

class D: public B {

public:

virtual void f;

};


Предполагается, что функция D::f будет переопределять виртуальную функцию B::f, но ошибка состоит в следующем: в классе B функция-член f – константная, а в D она не объявляется как const. Один из известных мне компиляторов сообщает следующее:


warning: D::f hides virtual B::f

(предупреждение: D::f скрывает virtual B::f)


Многие неопытные программисты, получив подобное сообщение, говорят себе: «Конечно, D::f скрывает B::f – так и должно быть!» Они неправы. Вот что пытается сказать компилятор: f, объявленная в B, не была объявлена повторно в D, а полностью спрятана (объяснение причины этого явления см. в правиле 33). Если оставить без внимания данное предупреждение, это почти наверняка приведет к ошибочному поведению программы, и, чтобы найти причину, потребуются долгие часы отладки – при том, что компилятор давно уже все обнаружил.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже