En la implementación general, suponiendo que cualquier operación de T
puede , no puede proporcionar la garantía de excepción fuerte que implica abandonar el estado exactamente como estaba antes de la operación en caso de una excepción. Incluso si cada operación en la T
ofrece la garantía fuerte excepción:
template<class T>
void swap (T &a, T &b)
{
T temp (a); // [1]
a = b; // [2]
b = temp; // [3]
}
Si [1] lanza, la entrada se deja intacto, lo cual es bueno. Si [2] arroja, y asumiendo la fuerte garantía de excepción, los valores siguen intactos, lo cual es bueno. Pero si es [3] que arroja, a
ya ha sido modificado, lo que significa que después de que la excepción se propague por la pila, la persona que llama quedará con un estado que no es ni el original ni el final.
EDIT: Además, ¿cómo podemos resolverlo?
No hay una solución general. Pero en la mayoría de los casos puede proporcionar una operación segura swap
segura para sus tipos. Considere un vector<T>
, que administra internamente su estado mediante el uso de tres punteros (begin
, end
, capacity
). El general se swap
anterior puede tirar (no asignan, los constructores para el interior T
podrían lanzar ...), pero es trivial para proporcionar un no-tiro swap
aplicación:
template <typename T>
class vector {
T *b,*e,*c;
public:
void swap(vector<T>& rhs) {
using std::swap;
swap(b, rhs.b);
swap(e, rhs.e);
swap(c, rhs.c);
}
//...
};
template <typename T>
void swap(vector<T>& lhs, vector<T>& rhs) {
lhs.swap(rhs);
}
Debido a que la copia de punteros no puede lanzar , el swap
anterior ofrece la garantía de no-tiro, y si siempre implementa swap
siguiendo el patrón anterior (using std::swap;
seguido de llamadas no calificadas al swap
), ADL lo detectará como una mejor coincidencia que std::swap
.
+1 Iba a escribir lo mismo. Un enlace a [este artículo] (http://www.boost.org/community/exception_safety.html) sería una ayuda, y útil para aquellos que desean conocer en detalle la seguridad de las excepciones basadas en contratos. – Nawaz