2012-07-14 5 views

Respuesta

21

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

+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

2

Daniel tiene razón, por supuesto.

Pero no debe olvidar que cuando se trata de seguridad de excepciones, el intercambio se considera principalmente como parte de la solución (el "idioma de copiar y cambiar"), no es el problema. El problema restante es que si adoptas este modismo, tienes que asegurarte de que los constructores de copia que intercambian puedan llamar, no arrojen excepciones, por las razones explicadas por Daniel.

Ver: What is the copy-and-swap idiom?

0

la fuente de la excepción se ha explicado

pero se puede evitar que las excepciones echando los argumentos a unsigned byte* y el trueque de byte a byte hasta sizeof(T) nota esto no va a llamar a ningún constructor o destructores de los objetos que puede violar algunas condiciones previas cuando hay alguna referencia auto pasando (cuando a puntos a b después del intercambio a señalarán a a)

así es como lo hace el intercambio en la biblioteca estándar D (después de que comprueba la autorreferencia)

Cuestiones relacionadas