Una forma realmente mejor sería crear una clase (o clases) para las excepciones.
Algo como:
class ConfigurationError : public std::exception {
public:
ConfigurationError();
};
class ConfigurationLoadError : public ConfigurationError {
public:
ConfigurationLoadError(std::string & filename);
};
La razón es que las excepciones son mucho más preferibles que simplemente transferir una cadena. Al proporcionar diferentes clases para los errores, les da a los desarrolladores la oportunidad de manejar un error en particular de la manera correspondiente (no solo mostrar un mensaje de error). Las personas que detectan tu excepción pueden ser tan específicas como necesiten si usas una jerarquía.
a) Es posible que deba saber la razón específica
} catch (const ConfigurationLoadError & ex) {
// ...
} catch (const ConfigurationError & ex) {
a) otro no quiere saber detalles
} catch (const std::exception & ex) {
Puede encontrar algo de inspiración sobre este tema en https://books.google.ru/books?id=6tjfmnKhT24C Capítulo 9
Además, también puede proporcionar un mensaje personalizado, pero tenga cuidado, no es seguro redactar un mensaje de una std::stringu std::stringstreamotra forma que pueda causar una excepción .
En general, no hay diferencia si asigna memoria (trabaja con cadenas en C ++) en el constructor de la excepción o justo antes de lanzarla; la std::bad_allocexcepción se puede lanzar antes de la que realmente desea.
Entonces, un búfer asignado en la pila (como en la respuesta de Maxim) es una forma más segura.
Se explica muy bien en http://www.boost.org/community/error_handling.html
Entonces, la forma más agradable sería un tipo específico de excepción y evitar componer la cadena formateada (al menos al lanzar).
std∷exceptionno tienen un constructor conchar*arg.