динамической проверки спецификаций исключений к статической, как это делается в Java и других языках программирования. Коротко говоря, это просто означает поменять шило на мыло, т.е. один ряд проблем на другой. Пользователи языков со статической проверкой спецификаций исключений не менее часто предлагают перейти к динамической проверке…
Если вы перекрываете виртуальную функцию базового класса, которая уже имеет спецификацию исключений, и у вас нет возможности внести изменения в базовый класс и убрать спецификации исключений (или убедить сделать это автора класса), то вы должны использовать совместимую спецификацию исключений в вашей перекрывающей функции, причем следует сделать ее не менее ограничивающей, чем в базовой версии, чтобы минимизировать возможность нарушений спецификации исключений:
class Base { //... // В чужом классе имеется
virtual f() // спецификация исключений,
throw(X, Y, Z) ; // и если вы не можете
}; // ее удалить...
class MyDerived
: public Base { //... // ... то в вашем классе при
virtual f() // перегрузке функции она должна
throw(X, Y, Z); // иметь совместимую (желательно
}; // идентичную) спецификацию исключений
Из опыта [BoostLRG] следует, что только пустые спецификации исключений (т.е. throw()
) у невстраиваемых функций 'могут давать некоторое преимущество у некоторых компиляторов'. Не слишком оптимистичное заявление для одного из наиболее продвинутых, разрабатываемого экспертами мирового уровня проекта…
STL: контейнеры
Если вам нужен контейнер, по умолчанию используйте vector
.
Мы знаем, что вы уже предпочитаете использовать стандартные контейнеры вместо написанных вручную. Но какой именно контейнер следует использовать? Что должно (и что не должно) храниться в контейнерах и почему? Как следует заполнять контейнеры? Какие важные идиомы надо знать?
В этом разделе имеются ответы на все перечисленные (и не только) вопросы. И не случайно, что три первые рекомендации в нем содержат слова 'Используйте vector
...'.
В этом разделе мы считаем наиболее значимой рекомендацию 79 — 'Храните в контейнерах только значения или интеллектуальные указатели'. К ней мы добавим — если даже вы не планируете применять [Boost] и [C++TR104] для иных целей, все равно воспользуйтесь их интеллектуальным указателем shared_ptr
.
76. По умолчанию используйте vector
. В противном случае выбирайте контейнер, соответствующий задаче
Очень важно использовать 'правильный контейнер'. Если у вас есть весомые причины выбрать определенный тип контейнера, используйте тот контейнер, который наиболее подходит для вашей задачи.
Если конкретных предпочтений нет, возьмите vector
и спокойно работайте, зная, что вы сделали верный выбор.
Ниже представлены три главных аспекта, которые касаются программирования вообще, и выбора контейнера в частности.
• vector
, list
). Если вам нужен итератор произвольного доступа, выберите vector
, deque
или string
. Если нужен словарный поиск наподобие c[0]=42;
, воспользуйтесь ассоциативным контейнером (например, set
, map
) — но если вам требуется упорядоченная ассоциативная коллекция, то вы не можете использовать контейнеры с использованием хеширования (нестандартные hash_
… или стандартные unordered_
… контейнеры).
• hash_
… или стандартными unordered_
… контейнерами), затем — отсортированным vector
, затем — set
или map
, обычно в приведенном порядке. Даже в этой ситуации отличия асимптотического времени работы (с использованием 'большого
• list
, set
, map
).
В противном случае следуйте совету Стандарта: 'vector
представляет собой тип последовательности, который нужно использовать по умолчанию' ([C++03] §23.1.1).
Если вы сомневаетесь в данном совете, спросите сами себя — действительно ли у вас есть непреодолимые причиныvector
, который обладает следующими свойствами.
• Гарантирует минимальные среди всех контейнеров накладные расходы памяти на хранение (ноль байтов на объект).
• Гарантирует наивысшую среди всех контейнеров скорость доступа к хранимым элементам.
• Гарантирует локальность ссылок, означающую, что объекты, находящиеся рядом друг с другом в