std::list<s> при push_back(s) копирует s посредством конструктора копирования(!) (по удалении списка вызывается деструктор каждого элемента). Сам list реализован через указатели как пишут в справочниках.
Логичнее исп-ть std::list<s*>, тогда не происходит копирование s, но с ним сложно работать с памятью, т.к. десрукторы придется вызывать вручную при удалении элементов и самого списка.
Поэтому лучше исп-ть boost::ptr_list<s>. Он автоматом вставляет объекты через ptr_list::push_back(*s). Происходит копирование указателя, а не объекта. В нем удаление происходит автоматически при исчезновении ссылки на s. (erase(iterator) & удаление списка происходит с полным удалением содержимого) Пример:
//testString наследует от string и выводит отладочные сообщения о том, что вызван конструктор/деструктор
1) Вариант с list<T*>:
struct DocObject {
public:
list<testString*> attrMapNames; //объявление списка указателей
public:
DocObject() {
attrMapNames.push_back(new testString("general")); //добавление элемента "general"; короткий способ
testString *s = new testString("additional");
attrMapNames.push_back(s); //способ с вспомогательной переменной типа указатель s
}
};
int main(int argc, char *argv[])
{
DocObject *dObj = new DocObject;
delete dObj;
return EXIT_SUCCESS;
}
__________
Программа выводит след.:
testString constructor called
testString constructor called
__________
Как видим, деструктор не вызван ни разу!
2) Вариант с ptr_list<T>:
struct DocObject {
public:
ptr_list<testString> attrMapNames; //обратите внимание, testString объявляется без '*'
public:
DocObject() { //код аналогичен вышеуказанному
attrMapNames.push_back(new testString("general"));
testString *s = new testString("additional");
attrMapNames.push_back(s);
}
};
int main(int argc, char *argv[])
{
DocObject *dObj = new DocObject;
delete dObj;
return EXIT_SUCCESS;
}
___________
Программа выводит след.:
testString constructor called
testString constructor called
testString destructor called
testString destructor called
___________
Как видим, на два конструктора = два деструктора вызвано. При этом никакого явного вызова деструкторов не требуется.
Обобщение. Пара слов об shared_ptr.
любой ptr_container забодится об удалении своих элементов вместе с собой, так что добавлять элементы такого контейнера в shared_ptr бессмысленно (ровно как и наоборот) и влечет за собой >=2-кратное удаление объекта и ошибки работы с памятью. shared_ptr имеет смысл использовать тогда когда у нас один единственный объект и не в контейнере. Для shared_ptr ссылок на объект может быть сколь угодно много.