Когда следует использовать std::nothrow?
Каково идеальное использование std::nothrow
?
9 ответов
Я бы использовал его только как оптимизацию (или упрощение кода), когда в противном случае я бы немедленно поместил блок try-catch вокруг использования регулярного нового, перехватывающего std::bad_alloc
,
Это довольно редкая ситуация, потому что редко можно эффективно использовать нехватку памяти прямо на месте вызова. Обычно вы выделяете память, потому что она вам нужна, а не потому, что вы хотели бы иметь ее, но можете жить без нее. Код, который передает нулевые указатели обратно в цепочку вызывающих, пока в конечном итоге кто-то не сможет решить проблему, не является идиоматическим C++.
Может случиться так, что ошибка действительно может быть обработана немедленно. Например, вы можете оказаться в ситуации, когда вы будете использовать один алгоритм или метод при наличии достаточного рабочего пространства, а другой - более медленный алгоритм или метод без него. Опять же, вы бы распределили такое рабочее пространство непосредственно с new
? Не нормально. И в любом случае вам иногда нужно быть осторожным с этим подходом, потому что если ваша ОС перегружена, то в целом вы не сможете изящно справиться с нехваткой памяти на уровне приложения.
Обратите внимание, что выражение, включающее std::nothrow, может по-прежнему генерировать исключение (в частности, из любого конструктора объекта, который выделяется), поэтому требуется только одна вещь, если вы хотите избежать выброса исключения. Вы также должны убедиться, что конструктор не выбросит.
Насколько я понимаю, дни программ на C++, которые вообще не используют исключения, прошли. Я полагаю, что если они возобновятся для меня из-за какого-то особого руководства по стилю, то это еще одна вероятная причина, по которой мне не нужно новое.
Портирование программы на C на C++. Ваша программа на С имеет все эти проверки после каждого malloc и не имеет понятия об исключениях. Поэтому гораздо проще изменить каждый malloc на новый (nothrow), чем заключать каждый malloc в блок try.
Возможно, если ваше приложение требует нано-оптимизации и не может допускать накладных расходов на обработку исключений, то, возможно, nothrow
будет необходимо.
Имейте в виду, что Страуструп довольно непреклонен, что программист может отключить накладные расходы в C++. (Как предостережение, хотя, только потому, что у вас есть выбор, не означает, что вы должны.)
Вы используете std::nothrow, когда хотите проверять наличие нуля после каждого нового. Много устаревшего кода нуждалось в этом, когда была сделана первая версия стандарта. Много унаследованного кода, написанного впоследствии, тоже используют его, потому что люди, где параноидальные исключения. Время от времени вы сталкиваетесь с кем-то, кто все еще есть.
Это настолько редко, что вы действительно захотите сделать это, что мне даже потребовалась секунда, чтобы вспомнить WTF, о котором вы говорили.
Я знаю, что были более старые версии C++ (в частности, Microsoft), которые не выдавали, когда они не могли выделить память, но вместо этого возвращали NULL. Это был бы простой способ поддерживать совместимость со старым кодом, а не изменять всю логику.
http://www.cplusplus.com/reference/std/new/nothrow/
Эта конструкция используется редко, потому что я подозреваю, что она не влияет на производительность выделения памяти, а может использоваться для удобства.
Тем не менее, я универсальный вариант, как правило, предпочтительнее.
Я могу себе представить, что это может быть использовано как оптимизация быстрого пути с использованием пользовательских распределителей - скажем, сбой текущего запроса и увеличение пула в более позднее / простое время. Практически угловой случай.
Лишь очень немногие программы должны когда-либо выделять более 1 ГБ памяти, и поскольку современные системы перегружают память, new
никогда не вернет null или throw в этих системах. Следовательно, абсолютно нет смысла проверять возвращаемое значение new / malloc. Просто уменьшите объем памяти и позвольте убийце нехватки памяти сбивать другие процессы!