typedef boost::shared_ptr
// to Widget"
vector
for (int i=0; i
vwp.push_back(SPW(new Widget)); //и вызвать push_back
… //Использовать vwp
} //Утечки Widget не происходит.
//даже если в предыдущем фрагменте
//произойдет исключение
auto_ptr
. Эта кошмарная мысль чревата такими неприятностями, что я посвятил ей совет 8.
Главное, что необходимо запомнить: контейнеры STL разумны, но они не смогут решить, нужно ли удалять хранящиеся в них указатели. Чтобы избежать утечки ресурсов при работе с контейнерами указателей, необходимо либо воспользоваться объектами умных указателей с подсчетом ссылок (такими, как shared_ptr
из библиотеки Boost), либо вручную удалить каждый указатель при уничтожении контейнера.
Напрашивается следующая мысль: если структура DeleteObject
помогает справиться с утечкой ресурсов для контейнеров, содержащих указатели на объекты, можно создать аналогичную структуру DeleteArray
, которая поможет избежать утечки ресурсов для контейнеров с указателями на массивы. Конечно, такое решение vector
и string
, поэтому прежде чем садиться за написание DeleteArray
, пожалуйста, прочитайте совет 13. Может быть, он убедит вас в том, что лучше обойтись без DeleteArray
.
Совет 8. Никогда не создавайте контейнеры, содержащие auto_ptr
Честно говоря, в книге, посвященной эффективному использованию STL, данный совет не совсем уместен. Контейнеры auto_ptr
(COAP, Containers Of Auto_Ptr) запрещены, а программа, которая попытается их использовать, не будет компилироваться. Комитет по стандартизации C++ приложил неслыханные усилия в этом направлении. Возможно, мне вообще не стоило бы говорить о контейнерах auto_ ptr
— о них вам расскажет компилятор, причем в самых нелестных выражениях.
Однако многие программисты работают на платформах STL, на которых COAP не запрещены. Более того, многие программисты по-прежнему подвержены иллюзии и видят в COAP простое, прямолинейное, эффективное средство для борьбы с утечкой ресурсов, часто присущей контейнерам указателей (советы 7 и 33). В результате возникает искушение воспользоваться COAP, даже если их невозможно создать.
Вскоре я объясню, почему COAP произвели такой переполох, что Комитет по стандартизации предпринял специальные шаги по их запрещению. А пока начнем с первого недостатка, для понимания которого не нужно разбираться в auto_ptr
и вообще в контейнерах: COAP не переносимы. Да и как может быть иначе? Они запрещены стандартом C++, и наиболее передовые платформы STL уже выполняют это требование. Вероятно, со временем платформы STL, которые сейчас не соответствуют Стандарту, выполнят его требования. Когда это произойдет, программы, использующие COAP, станут еще менее переносимыми, чем сейчас. Тот, кто заботится о переносимости своих программ, отвергнет COAP хотя бы по этой причине.
Впрочем, не исключено, что переносимость вас не волнует. Если это так, позвольте напомнить об уникальном (а по мнению некоторых — нелепом) смысле операции копирования auto_ptr
.
При копировании auto_ptr
право владения объектом, на который ссылается указатель, переходит к копии, а исходному указателю присваивается NULL. Да, вы не ошиблись:
auto_ptr
auto_ptr
//принадлежащий pw1; pw1 присваивается
//NULL (таким образом, объект Widget
//передается от pw1 к pw2)
pwl = pw2; //pw1 снова ссылается на Widget:
//pw2 присваивается NULL
Конечно, такое поведение необычно и даже по-своему интересно, но для пользователя STL в первую очередь важно то, что оно приводит к auto_ptr
и сортирует его функцией, сравнивающей значения Widget:
bool WidgetAPCompare(const auto_ptr