Подтвердить что ты не робот

Почему создание static const std::string вызывает исключение?

У меня есть строковые константы, для строк, которые я использую в нескольких местах в своем приложении:

namespace Common{
    static const std::string mystring = "IamAwesum";
}

Когда вы отправляете вопрос о чем-то еще (Что происходит с файлом .h, который не включен в цель во время компиляции?), другой пользователь сделал следующий комментарий

помните, что ваша статическая строка в этом случае является глобальной. Таким образом, они может создать исключение в любое время и не может быть уловом. Я советую тебе для использования функции, которая возвращает ссылку вашей строки. std::stringconst & mystring {static std::string const mystring = "IamAwesum"; return mystring} таким образом, ваш объект строится только при необходимости

Может кто-нибудь объяснить, почему использование статических константных строк таким образом, что я делаю это выше, рискует выбросить исключения?

4b9b3361

Ответ 1

N4140 § 3.6.2 [basic.start.init]/4

Определяется реализацией, является ли динамическая инициализация нелокальная переменная со статической продолжительностью хранения выполняется до первый оператор main.

N4140 § N4140 15.3 [кроме ручки]/13

Исключения, брошенные в деструкторы объектов со статическим хранилищем длительность или в конструкторах объектов пространства имен со статическими длительность хранения не улавливается функцией-try-block на main().

Вы просто не можете поймать исключение, сгенерированное конструктором строк - скажем, std::bad_alloc.

(мнение) Если сказать, что для таких маленьких строк я считаю такое рассмотрение параноидальным.

Ответ 2

PDF-документ в основном относится к исключениям из фиаско объекта ctor и инициализации с помощью статических или динамически связанных библиотек.

Единственная опасность, которую я вижу в вашем коде для исключений, - это то, что ctor std::string будет бросать, когда он вызывается.

Если вы действительно хотите быть в безопасности, вместо этого вы можете использовать статический const char * mystring, который не будет вызывать С++ ctor.

Также существует вопрос о том, что код находится в общей библиотеке, которая затем должна быть помещена в адресное пространство процесса. Я не вижу в этом серьезной проблемы, если вы не используете сложные ctors (ctors, которые могут бросать).

Ответ 3

Единственная "проблема" - если вы можете назвать ее так, что я вижу с вашим кодом, так это то, что вы расточительны, ненужно копируя данные, которые уже являются константами в динамически распределенный буфер (который формально постоянный, но не в действительности). Это использует в два раза больше физической памяти по мере необходимости и делает ненужную копию.

Это имеет значение? Почти наверняка нет. Даже в системе с довольно ограниченной памятью это в настоящее время вряд ли будет заметным ни с точки зрения времени выполнения, ни из-за потребления памяти.

Что касается исключений, то, конечно, технически верно, что выделение, которое std::string должно выполнить, может потерпеть неудачу, и, следовательно, конструктор может выбросить, и вы не сможете его поймать. Но, пожалуйста, будьте реалистами. Это почти гарантировано не произойдет, но даже если это произойдет... если что-то столь же тривиальное, как выделение памяти для пары строк, сбой при запуске вашей программы, у вас действительно действительно серьезная проблема в совершенно другом масштабе! < ш > Кроме того, как указано в комментарии к другому ответу выше: Предполагая, что это произойдет, что вы собираетесь с этим делать? Программа полностью не может работать, поэтому не так много, чтобы убить программу, которую вы могли бы сделать.

Теперь, когда С++ 17 не находится далеко и string_view уже доступен в std::experimental для нескольких компиляторов mainstream, вы можете попробовать другое: используйте правильную вещь.

A string_view будет, вопреки a string, не выделять непостоянную память, скопировать в нее постоянные данные, а затем сделать вид константы. Вместо этого он будет управлять указателем непосредственно с постоянными данными, и все.
Таким образом, ваши константы действительно (не только формально) постоянны, нет никаких распределений, нет возможности исключений и нет использования двойной памяти. И по большей части он по-прежнему выглядит и пахнет как string. Единственными заметными отличиями являются то, что a string_view не гарантирует nul-term (но постоянная символа, на которую указывает, делает это неактуальной), и тот факт, что он действительно постоянный, не изменяемый... что именно вы хотите.