Слишком часто мы слышим: «Я не хочу использовать исключения, потому что они неэффективны».
Если вы не имеете в виду «встроенную» среду, в которой вы хотите отключить всю информацию о типе среды выполнения, вам следуетне стоит слишком беспокоиться о неэффективности исключений, если они выбрасываются соответствующим образом.Недостаточно памяти - один из этих подходящих способов.
Часть контракта вектора заключается в том, что он выбросит, если не сможет выделить.Если вы пишете пользовательский распределитель, который вместо этого возвращает NULL, это будет хуже, так как это приведет к неопределенному поведению.
Если вам придется использовать распределитель, который сначала попытается выполнить обратный вызов неудачного размещения, если он доступен,и только тогда, если вы все еще не можете выделить для броска, но все же вы должны получить исключение.
Могу ли я дать вам подсказку: если вы действительно выделяете такие большие объемы данных, тогда вектор, вероятно,неправильный класс для использования, и вы должны использовать вместо него std :: deque.Зачем?Поскольку deque не требует непрерывного блока памяти, но все еще является постоянным поиском по времени.И преимущества двояки:
- Распределения будут отказывать реже.Поскольку вам не нужен непрерывный блок, так что вы вполне можете иметь доступную память, хотя и не в одном блоке.
- Перераспределения нет, просто больше выделений.Перераспределение дорогостоящее, так как требует перемещения всех ваших объектов.Когда вы работаете в режиме большого объёма, это может быть очень своевременной операцией.
Когда я в прошлом работал над такой системой, мы обнаружили, что на самом деле мы можем хранить более 4 разс помощью deque можно использовать столько данных, сколько мы могли использовать vector по причине 1, приведенной выше, и быстрее по причине 2.
Что-то еще мы делали, выделяя резервный буфер объемом 2 МБ, и когда мы перехватывали bad_alloc, мыосвободил буфер и затем бросил все равно, чтобы показать, что мы достигли емкости.Но с запасом 2 МБ теперь мы по крайней мере знали, что у нас есть память для выполнения небольших операций по перемещению данных из памяти во временное дисковое хранилище.
Таким образом, мы можем иногда перехватывать bad_alloc и предпринимать соответствующие действия, сохраняя согласованное состояниеЭто является целью исключений, а не предположения, что нехватка памяти всегда фатальна и никогда не должна делать ничего, кроме завершения программы (или, что еще хуже, вызывать неопределенное поведение).