В чем смысл shared_ptr для контейнера? - PullRequest
2 голосов
/ 15 августа 2011

Какой смысл декларировать boost::shared_ptr для контейнера типа std::vector или std::list?

Вот пример использования BOOST_AUTO.

void someFunction()
{
  ...
  BOOST_AUTO(sharedPtrToContainer, boost::make_shared<std::vector<T>>());
  ...
}

Есть ли смысл, если вам нужен только контейнер локально?В чем выгода?Каковы будут shared_ptr для контейнера?

Ответы [ 3 ]

8 голосов
/ 15 августа 2011

Какой смысл декларировать boost::shared_ptr для контейнера типа std::vector или std::list?

Точно такая же точка, что и использование общего указателя на любой тип объекта; это позволяет вам делиться собственностью объекта с другими областями. Не имеет значения, что объект является контейнером.

Есть ли смысл, если вам нужен только контейнер локально?

Нет; если он нужен только локально, то это должен быть обычный автоматический объект.

В чем выгода? Каковы будут shared_ptr для контейнера?

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

2 голосов
/ 15 августа 2011

Если вы просто объявляете контейнер, полный указателей на объекты, расположенные в куче, очень легко, если вы не будете осторожны, позволить контейнеру выйти из области видимости, и в этот момент у вас будет утечка памяти. Это связано с тем, что контейнер становится владельцем только того типа, который выделен в контейнере. Например, для std::vector<T*> вектор будет поддерживать владение только распределением памяти, чтобы содержать серию указателей ... он не будет поддерживать владение объектами, на которые указывают указатели. Это просто потому, что он не может ... как контейнер узнает, что он указывает на объект кучи, а не на что-то еще? И если бы он указывал на объект кучи, откуда ему было знать, что это единственная ссылка на этот объект кучи, и он мог удалять его при необходимости и не создавать кучу свисающих указателей? Реальность такова, что контейнеры STL не несут такого рода глобальную информацию о состоянии, они не могут знать ответы на эти вопросы, и поэтому единственной памятью, управляемой контейнером STL, является память, которую он выделяет для своих собственных объектов, которые он управления. Таким образом, когда контейнер, хранящий указатели, выходит из области видимости, память, используемая для размещения указателей, будет должным образом уничтожена, но сам контейнер не будет вызывать delete для каждого указателя, чтобы освободить объект, на который указывал каждый указатель на куча. Использование std::shared_ptr<T> в качестве типа для контейнера STL позволяет контейнеру выходить за пределы области и удалять память, выделенную для каждого shared_ptr, выделенного в массиве. Однако из-за информации о состоянии объекта подсчета ссылок, хранящейся в shared_ptr, после удаления последней ссылки на объект он сам будет должным образом уничтожать объект в куче, которой он управляет. Поэтому, если у вас был контейнер STL, вышедший из области видимости, любой shared_ptrs в этом контейнере, который был последней ссылкой на объект, на который они указывали, правильно уничтожил бы объект в куче, и вы бы не оказались в конечном итоге с серией утечек памяти из указателей, теряемых объектами кучи.

0 голосов
/ 15 августа 2011

Если вам это нужно только локально, используйте автоматический экземпляр:

std::vector<T> inst;

Если вам нужно вернуться, а T тяжелый (или вектор смехотворно большой), тогда используйте либо shared_ptr или вектор указателей (T тяжелый и маленький), в противном случае возврат по значению, например vector<int>, в зависимости от размера, может также возвращаться по значению (я полагаю, сильно зависит от того, что будет делать вызывающая сторонас этим) ...

...