Diferencia entre la syntax try-catch para la función

Me encontré con esta syntax recientemente para try-catch para la función.

 struct A { int a; A (int i) : a(i) // normal syntax { try {} catch(...) {} } A () // something different try : a(0) {} catch(...) {} void foo () // normal function try {} catch(...) {} }; 

Ambas syntax son válidas . ¿Hay alguna diferencia técnica entre estas syntax además del estilo de encoding? ¿Es una syntax superior a la otra en cualquier aspecto?

La primera syntax:
El scope del bloque try se inicia después de que se haya completado la lista de inicialización de miembros, por lo que cualquier excepción lanzada durante la inicialización del miembro no será capturada por este bloque try-catch.

La segunda syntax:
Asegura que si se lanza una excepción durante la lista de Inicialización de miembros, entonces puede atrapar la excepción.

La tercera syntax:
Asegura que cualquier excepción lanzada entre el corchete inicial del bloque try dentro del cuerpo de la función quede atrapada apropiadamente. Significaría que cualquier excepción causada durante el paso del argumento (si puede ocurrir) no será capturada en este bloque try-catch.

Entonces sí, son claramente diferentes en cuanto a la funcionalidad que proporcionan.


EDITAR:
Algunas pautas que se deben considerar al usar la segunda syntax (function-try-block) en constructores y destructores:

Según el estándar C ++,

Si el bloque de catch no arroja (ni vuelve a lanzar la excepción original, ni tira algo nuevo), y el control llega al final del bloque catch de un constructor o destructor, entonces la excepción original se vuelve a lanzar automáticamente.

En palabras simples:
El código de controlador constructor o destructor function-try-block DEBE finalizar emitiendo alguna excepción.

Directriz 1:
Los manejadores de función-bash-locking de constructor tienen un solo propósito: traducir una excepción. (Y tal vez para iniciar sesión u otros efectos secundarios.) No son útiles para ningún otro propósito.

Lanzar una excepción de los destructores es una mala idea. Echa un vistazo aquí para saber por qué.
Directriz 2:
Destructor function-try-blocks no tiene ningún uso práctico en absoluto. Nunca debe haber nada que puedan detectar, e incluso si hubiera algo que detectar debido al código maligno, el controlador no es muy útil para hacer algo al respecto, ya que no puede suprimir la excepción.

Directriz 3:
Siempre limpie la adquisición de recursos no administrados en manejadores de try-block locales dentro del constructor o del cuerpo del destructor, nunca en los manejadores de constructor-try-block de constructor o destructor.


Para los fanáticos standardese:

Norma C ++, cláusula 15.3, párrafo 15:

Si aparece una statement return en un controlador de la función-try-block de un constructor, el progtwig está mal formado.

Norma C ++, cláusula 15.3, párrafo 16:

La excepción que se maneja se vuelve a lanzar si el control llega al final de un controlador de la función-try-block de un constructor o destructor. De lo contrario, una función regresa cuando el control llega al final de un controlador para la función-try-block (6.6.3). Fluir fuera del final de una función-try-block es equivalente a un retorno sin valor; esto da como resultado un comportamiento indefinido en una función de devolución de valor (6.6.3).


Referencias
Eche un vistazo a este recurso que debe leer aquí para obtener más detalles y explicaciones.

Function-try-block es útil principalmente en constructores, porque no hay otra forma de capturar excepciones en la lista de inicialización. En los destructores se debe tener cuidado de volver en el bloque catch, ya que la excepción se volverá a lanzar automáticamente. (Y en el buen diseño, los destructores no deben lanzar.) En las funciones normales, esta característica no es útil. Editar: un artículo antiguo pero bueno: http://drdobbs.com/184401316

Podría citar la especificación … O al menos un borrador .

Sección 15 (4):

Un function-try-block asocia un handler-seq con el ctor-initializer , si está presente, y el compuesto-statement . Una excepción arrojada durante la ejecución de la sentencia compuesta o, para constructores y destructores, durante la inicialización o destrucción, respectivamente, de los subobjetos de la clase, transfiere el control a un manejador en una función-try-block de la misma manera que una excepción lanzada durante la ejecución de un control try-block transfiere a otros manejadores.

(Aquí el manejador-seq es el material después de la catch y el compound-statement es el cuerpo de la función).

Por lo tanto, el “bloque de prueba de función” en un constructor o destructor detecta excepciones lanzadas por los inicializadores de ctor y por la construcción o destrucción de subobjetos.

En una función que no sea un constructor o un destructor, es lo mismo que simplemente envolver el cuerpo de la función. (Bueno, por lo que puedo discernir al leer las especificaciones)

Una característica interesante y nueva para mí. Gracias por sacar el tema.

El ejemplo “algo diferente” coloca el procesamiento de la lista de inicializadores dentro del scope del bloque try.