Уничтожение строковых временных в брошенных исключениях - PullRequest
5 голосов
/ 10 марта 2010

Рассмотрим следующий код:

std::string my_error_string = "Some error message";

// ...

throw std::runtime_error(std::string("Error: ") + my_error_string);

Строка, переданная в runtime_error, является временным значением, возвращаемым строкой operator+. Предположим, что это исключение обрабатывается примерно так:

catch (const std::runtime_error& e)
{
    std::cout << e.what() << std::endl;
}

Когда уничтожается временное значение, возвращаемое operator+ строки? В спецификации языка есть что сказать по этому поводу? Также предположим, что runtime_error принял аргумент const char* и был выдан следующим образом:

// Suppose runtime_error has the constructor runtime_error(const char* message)
throw std::runtime_error((std::string("Error: ") + my_error_string).c_str());

Теперь, когда временная строка, возвращаемая оператором +, уничтожается? Будет ли он уничтожен до того, как блок catch попытается его распечатать, и поэтому runtime_error принимает std :: string, а не const char *?

Ответы [ 3 ]

8 голосов
/ 10 марта 2010

runtime_error - это класс, который содержит строку. Эта строка будет управляться для вас обычными механизмами конструирования и уничтожения C ++. Если бы он содержал символ *, то этим нужно было бы явно управлять, но вам все равно не нужно было бы что-либо делать как пользователь из runtime_error.

Несмотря на то, что вы можете прочитать в другом месте в Интернете, C ++ разработан почти всегда для того, чтобы делать «разумные вещи» - вам на самом деле приходится изо всех сил пытаться нарушить это разумное поведение, хотя, конечно, это невозможно.

5 голосов
/ 10 марта 2010

Как временный объект (12.2), результат + будет уничтожен как последний шаг в оценке полного выражения (1.9 / 9), в котором он содержится. В этом случае полное выражение является throw-выражением .

A throw-выражение создает временный объект ( объект-исключение ) (15.1) (std::runtime_error в данном случае). Все временные объекты в throw-выражении будут уничтожены после того, как exception-object был построен. Исключение выдается только после того, как оценка throw-expression завершена, так как уничтожение временных элементов является частью этой оценки, они будут уничтожены до уничтожения автоматических переменных, созданных после ввода блока try ( 15.2) и до ввода обработчика.

Постусловие в конструкторе runtime_error состоит в том, что what() возвращает то, что strcmp считает равным тому, что возвращает c_str() в переданном аргументе. Теоретически возможно, что после уничтожения std::string, переданного в качестве аргумента конструктора, runtime_error what() может возвращать что-то другое, хотя это будет сомнительная реализация и все равно будет завершаться нулем какая-то строка, она не может вернуть указатель на устаревшую c_str() мертвую строку.

3 голосов
/ 10 марта 2010

Обратите внимание, что класс исключения runtime_error создает копию строки, переданной в конструктор. Поэтому, когда вы вызываете .what () для объекта исключения, вы не получаете тот же самый точный экземпляр строки, который вы передали.

Итак, чтобы ответить на ваш вопрос, временный объект, о котором вы спрашиваете, уничтожается "в точке с запятой" выражения, которое его содержит (это верно как в вашей первой, так и во второй версии вопроса), но, как я уже сказал это не так интересно, потому что его копия уже сделана.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...