28 июля 2006

Есть ли жизнь после assert()?

assert() - полезный макрос для документирования pre-conditions и отладки кода. Однако, не стоит забывать про release version, когда все эти ассерты превратяться в тыкву. Одно дело, когда условие assert-а зависит от внутреннего состояния программы, другое дело - если от внешних данных. Тут нужно менять assert() на что-то, что выживет в release.

Config = LoadConfig("config.cfg");
assert(Config != NULL);
Config->GetValue(...)


Вот в таком случае явно не место assert-у. Как минимум - throw std::exception("wtf w/config?")

19 июля 2006

Template Template Parameters

То, что параметры шаблона могут не только типами и классами, а еще и шаблонами, я узнал только читая Александреску (нет чтобы стандарт C++ почитать ;)).

В кратце суть шаблонных параметров шаблона:

template <typename T>
class Vector { ... }

template <typename T>
class Deque { ... }

template <template <typename> class Container>
class SomeClass
{
Container<SomeDataType> Data;
}

SomeClass<Vector> VectorObject;
SomeClass<Deque> DequeObject;

13 июля 2006

delete this

Конструкция delete this; выглядит довольно необычно. Выглядит, как будто мы рубим сук, на котором сидим. Однако, все довольно безопасно, если выполнять меры предосторожности (мыть руки перед едой ;)).

Что из себя представляют методы класса? Да это обычные функции, которым неявно передается указатель this.

void vector::remove(ItT it)
на самом деле выглядит примерно как
void ::remove(vector* this, ItT it)

Кстати, int vector::size() const
выглядит как int ::size(const vector* this).

Соответственно, внутри метода можно спокойно удалить какой-то объект, а называется он this или как-то по-другому - это все равно. Главное, не пользоваться этим объектом после удаления. Причем (внимание!) нужно перестать им пользоваться совсем, то есть не только в этом методе после выполнения delete this;, но и там, откуда этот метод вызван.

Но это еще не все предосторожности. Перед тем как сделать delete this; естественно надо убедиться, что объект создан через new, а не на стеке или еще как-то (каким-нибудь нестандартным аллокатором). Как убедиться в этом - вопрос дизайна (design). Можно просто написать в документации: "этот объект нужно создавать через new" или сделать конструкторы приватными и создат static-member-ов для создания объектов. Или вообще использовать boost:shared_ptr, и тогда вместо delete this; будет sp.release(), который удалит объект как ему предписывает назначенный deleter.

Ссылка по теме: ATL's CWindowImpl::OnFinalMessage() crash

04 июля 2006

STL and C++ Standard Library

Многие путают STL и стандартную библиотеку C++. Некоторые думают что это одно и то же.

На самом деле STL - библиотека, разработанная SGI, часть из которой включили в стандарт C++. Уже из этого вытекают два факта:
1. STL ≠ стандартная библиотека C++,
2. не все, что есть в STL, есть в стандартной библиотеке C++.

Если объяснять на пальцах: парни, разрабатывающие стандарт C++, в один день подумали - вон какие хорошие вещи есть в STL, давайте скопируем некоторые из них в наш стандарт. Скопировали не всё, например, в стандартной библиотеке C++ нет алгоритма copy_n, хотя он есть в STL.

Третье. Стандартная библиотека C++ намного шире STL: в ней есть потоки ввода-вывода, auto_ptr, и много чего другого. Так что говоря про стандартную библиотеку не стоит называть ее "STL".

Наиболее полную реализацию STL можно найти в STLPort.

PS. В следующем стандарте в стандартную библиотеку C++ будет включено много вещей из Boost-а, но это не повод называть стандартную библиотеку Boost-ом :)