79. Храните в контейнерах только значения или интеллектуальные указатели
79. Храните в контейнерах только значения или интеллектуальные указатели
Резюме
Храните к контейнерах объекты-значения. Контейнеры полагают, что их содержимое имеет тип значения, включая непосредственно хранящиеся значения, интеллектуальные указатели и итераторы.
Обсуждение
Наиболее распространенное использование контейнеров — для непосредственного хранения значений (например, vector<int>, set<string>). В случае контейнеров указателей, если контейнер владеет объектами, на которые указывает, то лучше использовать контейнер интеллектуальных указателей со счетчиком ссылок (например, list<shared_ptr<Widget> >); в противном случае можно выбрать контейнер обычных указателей (например, list<Widget*>) или иных значений, подобных указателям — таких как итераторы (например, list<vector<Widget>::iterator>).
Примеры
Пример 1. auto_ptr. Объекты auto_ptr<T> не являются объектами-значениями из-за своей семантики передачи владения при копировании. Использование контейнера объектов auto_ptr (например, vector<auto_ptr<int> >) должно привести к ошибке компиляции. Но даже в случае успешной компиляции никогда не пишите такой код — вместо этого вам следует использовать контейнер интеллектуальных указателей shared_ptr.
Пример 2. Гетерогенные контейнеры. Для того чтобы получить контейнер, хранящий и владеющий объектами различных, но связанных типов, например, типов, производных от общего базового класса, лучше использовать container<shared_ptr<Base> >. Альтернативой является хранение прокси-объектов, невиртуальные функции которых передают вызовы соответствующим виртуальным функциям реальных объектов.
Пример 3. Контейнеры типов, не являющихся значениями. Для того чтобы хранить объекты, несмотря на невозможность их копирования или другое их поведение, делающее их типами, не являющимися значениями (например, DatabaseLock или TcpConnection), их следует хранить опосредованно, с использованием интеллектуальных указателей (например, container<shared_ptr<DatabaseLock> > или container<shared_ptr<TcpConnection> >).
Пример 4. Необязательные значения. Если вам нужен контейнер map<Thing,Widget>, но некоторые Thing не имеют связанных с ними объектов Widget, можно использовать map<Thing, shared_ptr<Widget> >.
Пример 5. Индексные контейнеры. Если вам нужен контейнер, хранящий объекты, и доступ к ним с использованием разных видов упорядочения без пересортировки основного контейнера, вы можете воспользоваться вторичным контейнером, который "указывает в" основной контейнер, и отсортировать его различными способами с применением предикатов сравнения с разыменованием. Однако вместо контейнера указателей лучше использовать контейнер объектов типа MainContainer::iterator (которые являются значениями).
Ссылки
[Allison98] §14 • [Austern99] §6 • [Dewhurst03] §68 • [Josuttis99] §5.10.2 • [Koenig97] §5 • [Meyers01] §3, §7-8 • [SuttHysl04b]
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
8.11 Переход на более интеллектуальные протоколы
8.11 Переход на более интеллектуальные протоколы Для перехода на более интеллектуальные протоколы были сделаны два улучшения. Как и RIP, лицензированный протокол IGRP компании Cisco использует вектор расстояния, однако в нем устранены недостатки RIP. OSPF и IS-IS являются
Указатели
Указатели Указатель в С++ — это переменная, содержащая не сам объект, а адрес памяти, где располагается объект. Java и C# имеют аналогичную концепцию «ссылки» при другом синтаксисе. Мы начнем с рассмотрения придуманного нами примера, иллюстрирующего применение указателей:01
R.8.2.1 Указатели
R.8.2.1 Указатели В описании T D, в котором D имеет вид* список-спецификаций-cv opt D1тип описываемого идентификатора есть"… список-спецификаций-cv указатель на T". Конструкция список-спецификаций-cv относится к указателю, а не к указуемому объекту.Например, в описанияхconst ci = 10, *pc =
R.8.2.3 Указатели на члены
R.8.2.3 Указатели на члены В описании T D, в котором D имеет видполное-имя-класса :: * список-спецификаций-cv opt D1тип описываемого идентификатора есть "… список-спецификаций-cv указатель на член класса полное-имя-класса типа T".Например, во фрагментеclass X {public: void f(int); int a;};int X::* pmi =
57. Храните типы и их свободный интерфейс в одном пространстве имен
57. Храните типы и их свободный интерфейс в одном пространстве имен РезюмеФункции, не являющиеся членами и разработанные как часть интерфейса класса X (в особенности операторы и вспомогательные функции), должны быть определены в том же пространстве имен, что и X, что
58. Храните типы и функции в разных пространствах имен, если только они не предназначены для совместной работы
58. Храните типы и функции в разных пространствах имен, если только они не предназначены для совместной работы РезюмеОберегайте ваши типы от непреднамеренного поиска, зависящего от аргументов (argument-dependent lookup — ADL, известный также как поиск Кёнига); однако преднамеренный
6.9. Хранение контейнеров в контейнерах
6.9. Хранение контейнеров в контейнерах ПроблемаИмеется несколько экземпляров стандартного контейнера (list, set и т.п.) и требуется сохранить их в еще одном контейнере.РешениеСохраните в главном контейнере указатели на остальные контейнеры. Например, можно использовать map
Свойства, доступные только для чтения, и свойства, доступные только для записи
Свойства, доступные только для чтения, и свойства, доступные только для записи При создании типов класса можно создавать свойства, доступные только для чтения. Для этого просто создайте свойство без соответствующего блока set. Точно так же, если вы хотите иметь свойство,
Совет 22. Избегайте изменения ключа «на месте» в контейнерах set и multiset
Совет 22. Избегайте изменения ключа «на месте» в контейнерах set и multiset Понять смысл этого совета нетрудно. Контейнеры set/multiset, как и все стандартные ассоциативные контейнеры, хранят свои элементы в отсортированном порядке, и правильное поведение этих контейнеров зависит
1. Пустые значения (Empty-значения)
1. Пустые значения (Empty-значения) Пустое значение – это просто одно из множества возможных значений какого-то вполне определенного типа данных.Перечислим наиболее «естественные», непосредственные пустые значения (т. е. пустые значения, которые мы могли бы выделить
2. Неопределенные значения ( Null-значения)
2. Неопределенные значения (Null-значения) Слово Null используется для обозначения неопределенных значений в базах данных.Чтобы лучше понять, какие значения понимаются под неопределенными, рассмотрим таблицу, являющуюся фрагментом базы данных: Итак, неопределенное
3.3. Указатели
3.3. Указатели Указатели и динамическое выделение памяти были вкратце представлены в разделе 2.2. Указатель – это объект, содержащий адрес другого объекта и позволяющий косвенно манипулировать этим объектом. Обычно указатели используются для работы с динамически
7.2.4 Указатели
7.2.4 Указатели Если производный класс derived имеет открытый базовый класс base, то указатель на derived можно присваивать перменной типа указатель на base не используя явное преобразовние типа. Обратное преобразование, указателя на base в указтель на derived, должно быть явным.
На что способны «интеллектуальные» видеосистемы безопасности
На что способны «интеллектуальные» видеосистемы безопасности Естественно, видеосистему невозможно представить себе без видеокамер. В зависимости от технических характеристик того или иного комплекса их может быть от 2–4 до нескольких десятков штук.Понятно, что сигнал,
Указатели
Указатели Указатель - это ячейка памяти, хранящая адрес. В PascalABC.NET указатели делятся на типизированные (содержат адрес ячейки памяти данного типа) и бестиповые (содержат адрес оперативной памяти, не связанный с данными какого-либо определенного типа).Тип указателя на