Проектирование новой системы с нуля. Я буду использовать STL для хранения списков и карт определенных долгоживущих объектов.
Вопрос: Должен ли я гарантировать, что мои объекты имеют конструкторы копирования и хранят копии объектов в моих контейнерах STL, или лучше вообще управлять жизнью и областью действия и просто хранить указатели на эти объекты в моих контейнерах STL?
Я понимаю, что это несколько не хватает деталей, но я ищу «теоретический» лучший ответ, если он существует, поскольку я знаю, что оба эти решения возможны.
Два очень очевидных недостатка в игре с указателями: 1) Я должен сам управлять распределением / освобождением этих объектов за пределами STL. 2) Я не могу создать временный объект в стеке и добавить его в мои контейнеры.
Есть что-то еще, что я пропускаю?
Ответы:
Так как люди вмешиваются в эффективность использования указателей.
Если вы планируете использовать std :: vector и если обновлений немного, и вы часто выполняете итерацию по своей коллекции, и это не полиморфный тип, то хранение «копий» объекта будет более эффективным, поскольку вы получите лучшую локальность ссылок.
Otoh, если обновления являются распространенными указателями хранения, это сэкономит затраты на копирование / перемещение.
источник
Это действительно зависит от вашей ситуации.
Если ваши объекты маленькие, а копирование объекта является легковесным, то хранение данных в контейнере stl, на мой взгляд, является простым и более простым в управлении, поскольку вам не нужно беспокоиться об управлении временем жизни.
Если у вас большие объекты, и использование конструктора по умолчанию не имеет смысла, или копии объектов стоят дорого, то хранение с указателями, вероятно, является подходящим способом.
Если вы решили использовать указатели на объекты, взгляните на библиотеку Boost Pointer Container . Эта библиотека повышения оборачивает все контейнеры STL для использования с динамически размещаемыми объектами.
Каждый контейнер указателя (например, ptr_vector) становится владельцем объекта при его добавлении в контейнер и управляет временем жизни этих объектов для вас. Вы также получаете доступ ко всем элементам в контейнере ptr_ по ссылке. Это позволяет вам делать такие вещи, как
Эти классы обертывают контейнеры STL и работают со всеми алгоритмами STL, что действительно удобно.
Существуют также средства для передачи владения указателем в контейнере вызывающей стороне (с помощью функции освобождения в большинстве контейнеров).
источник
Если вы храните полиморфные объекты, вам всегда нужно использовать набор указателей базового класса.
То есть, если вы планируете хранить разные производные типы в своей коллекции, вы должны хранить указатели или быть съеденными даемоном.
источник
Извините, что прыгнул через 3 года после события, но предостережение здесь ...
В моем последнем большом проекте моей центральной структурой данных был набор довольно простых объектов. Примерно через год после разработки требований я понял, что объект должен быть полиморфным. Потребовалось несколько недель сложной и неприятной операции на головном мозге, чтобы исправить структуру данных как набор указателей базового класса и справиться со всеми сопутствующими повреждениями при хранении объектов, приведениях и т. Д. Мне потребовалось несколько месяцев, чтобы убедить себя, что новый код работает. Кстати, это заставило меня задуматься о том, насколько хорошо разработана объектная модель C ++.
В моем текущем большом проекте моя центральная структура данных представляет собой набор довольно простых объектов. Примерно через год в проекте (который происходит сегодня), я понял, что объект на самом деле должен быть полиморфным. Обратно в сеть, нашел эту ветку и нашел ссылку Ника на библиотеку контейнера указателя Boost. Это именно то, что я должен был написать в прошлый раз, чтобы все исправить, поэтому я попробую на этот раз.
Мораль, для меня, в любом случае: если ваша спецификация не на 100% отлита в камне, используйте указатели, и вы потенциально можете сэкономить много работы позже.
источник
Почему бы не получить лучшее из обоих миров: сделайте контейнер умных указателей (таких как
boost::shared_ptr
илиstd::shared_ptr
). Вам не нужно управлять памятью, и вам не нужно иметь дело с большими операциями копирования.источник
Как правило, хранение объектов непосредственно в контейнере STL является наилучшим, поскольку оно является самым простым, наиболее эффективным и наиболее простым для использования объекта.
Если ваш объект имеет не копируемый синтаксис или является абстрактным базовым типом, вам нужно хранить указатели (проще всего использовать shared_ptr)
источник
Вы, кажется, хорошо понимаете разницу. Если объекты маленькие и их легко скопировать, то непременно сохраните их.
Если нет, я бы подумал о сохранении умных указателей (не auto_ptr, умный указатель подсчета ссылок) для тех, которые вы выделяете в куче. Очевидно, что если вы выбираете умные указатели, то вы не можете хранить выделенные объекты временного стека (как вы уже сказали).
@ Torbjörn хорошо подходит к нарезке.
источник
one
toanother
освободит ссылку изone
и изменитсяone
.Использование указателей будет более эффективным, поскольку контейнеры будут копировать только указатели, а не полные объекты.
Здесь есть некоторая полезная информация о контейнерах STL и умных указателях:
Почему неправильно использовать std :: auto_ptr <> со стандартными контейнерами?
источник
Если на объекты нужно ссылаться в другом месте кода, храните в векторе boost :: shared_ptr. Это гарантирует, что указатели на объект останутся действительными, если вы измените размер вектора.
То есть:
Если никто не хранит указатели на объекты или список не увеличивается и не уменьшается, просто храните как обычные старые объекты:
источник
Этот вопрос беспокоит меня некоторое время.
Я склонен хранить указатели, но у меня есть некоторые дополнительные требования (SWIG lua wrappers), которые могут не относиться к вам.
Самым важным моментом в этом посте является тестирование самостоятельно , используя ваши объекты
Я сделал это сегодня, чтобы проверить скорость вызова функции-члена в коллекции из 10 миллионов объектов 500 раз.
Функция обновляет x и y на основе xdir и ydir (все переменные-члены с плавающей точкой).
Я использовал std :: list для хранения обоих типов объектов и обнаружил, что сохранение объекта в списке немного быстрее, чем использование указателя. С другой стороны, производительность была очень близка, поэтому все сводится к тому, как они будут использоваться в вашем приложении.
Для справки, с -O3 на моем оборудовании указателям потребовалось 41 секунда, а необработанным объектам потребовалось 30 секунд.
источник