C ++ - это мультипарадигмальный язык.Он сияет ярче всего и наиболее силен там, где смешаны парадигмы.
class Property
{
public:
Property(const std::string& name) //note: we don't lightly copy strings in C++
: m_name(name) {}
virtual ~Property() {}
private:
std::string m_name;
};
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const std::string& name, const T& data)
: Property(name), m_data(data);
private:
T m_data;
};
typedef std::vector< std::shared_ptr<Property> > property_list_type;
Редактировать: Зачем использовать std::shared_ptr<Property>
вместо Property*
?
Рассмотрим этот код:
void f()
{
std::vector<Property*> my_property_list;
for(unsigned int u=0; u<10; ++u)
my_property_list.push_back(new Property(u));
use_property_list(my_property_list);
for(std::vector<Property*>::iterator it=my_property_list.begin();
it!=my_property_list.end(); ++it)
delete *it;
}
То, что цикл for
там пытается очистить, удаляя все свойства в векторе, как раз перед тем, как он выходит из области видимости и забирает все указатели с ним.
Теперь, хотя это может показаться новичку новостью,если вы только немного опытный разработчик C ++, этот код должен вызывать тревожные сигналы, как только вы на это смотрите.
Проблема в том, что вызов use_property_list()
может вызвать исключение.Если это так, функция f()
будет сразу же оставлена.Для правильной очистки будут вызваны деструкторы для всех автоматических объектов, созданных в f()
.То есть my_property_list
будет должным образом уничтожено.Деструктор std::vector
затем аккуратно очистит содержащиеся в нем данные. Однако он содержит указатели , и как std::vector
знать, являются ли эти указатели последними, ссылающимися на их объекты?
Поскольку он не знает, он не будетудаляя объекты, он будет уничтожать указатели только тогда, когда уничтожает его содержимое, оставляя вас с объектами в куче, к которым у вас больше нет указателей.Это то, что называется «утечка».
Чтобы избежать этого, вам нужно будет перехватить все исключения, очистить свойства и перезапустить исключение.Но затем, через десять лет, кто-то должен добавить новую функцию в приложение 10MLoC, к которому она выросла, и, спеша, добавляет код, который преждевременно покидает эту функцию, когда выполняется какое-то условие.Код протестирован, и он работает и не дает сбоя - только сервер, частью которого он является, теперь теряет несколько байтов в час, что приводит к сбою из-за нехватки памяти примерно раз в неделю.Обнаружение того, что в течение многих часов отлично отлаживается.
Итог: никогда не управляйте ресурсами вручную, всегда заключайте их в объекты класса, предназначенного для обработки ровно одного экземпляра такого ресурса.Для динамически размещаемых объектов эти дескрипторы называются «умным указателем» , а наиболее часто используемым является shared_ptr
.