Diferença entre a syntax try-catch da function

Eu me deparei com essa syntax recentemente para try-catch a function.

 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 as syntaxs são válidas . Existe alguma diferença técnica entre essas syntaxs além do estilo de codificação? Uma das syntaxs é superior a outra por qualquer aspecto?

A primeira syntax:
O escopo do bloco try é iniciado após a conclusão da lista de Inicialização do Membro. Portanto, qualquer exceção lançada durante a Inicialização do Membro não será capturada por este bloco try-catch.

A segunda syntax:
Isso garante que, se uma exceção for lançada durante a lista de Inicialização de Membro, você poderá capturar a exceção.

A terceira syntax:
Ele garante que qualquer exceção lançada entre a chave inicial do bloco try dentro do corpo da function seja capturada apropriadamente. Isso significaria que qualquer exceção causada durante a passagem do argumento (se alguma puder ocorrer) não será capturada neste bloco try-catch.

Então, sim, eles são diferentes em relação à funcionalidade que eles oferecem.


EDITAR:
Algumas diretrizes a serem consideradas ao usar a segunda syntax (function-try-block) em construtores e destruidores:

De acordo com o padrão C ++,

Se o bloco catch não for lançado (ou voltar a exibir a exceção original ou lançar algo novo) e o controle atingir o final do bloco catch de um construtor ou destruidor, a exceção original será automaticamente liberada.

Em palavras simples:
Um construtor ou código manipulador do destruidor function-try-block DEVE terminar emitindo alguma exceção.

Diretriz 1:
Manipuladores de function-try-block de construtor têm apenas um propósito – para traduzir uma exceção. (E talvez para fazer log ou alguns outros efeitos colaterais). Eles não são úteis para qualquer outra finalidade.

Lançar uma exceção dos destruidores é uma má ideia. Dê uma olhada aqui para saber o motivo.
Diretriz 2:
Destructor function-try-blocks não tem nenhum uso prático. Nunca deve haver nada para eles detectarem, e mesmo que houvesse algo a ser detectado por causa do código maligno, o manipulador não é muito útil para fazer algo sobre isso porque não pode suprimir a exceção.

Diretriz 3:
Sempre limpe a aquisição de resources não gerenciados em manipuladores de blocos de tentativas locais dentro do corpo do construtor ou do destruidor, nunca nos manipuladores de construtor ou de function-tentativa-bloco do destruidor.


Para fãs de Standardese:

Norma C ++, cláusula 15.3, parágrafo 15:

Se uma instrução de retorno aparecer em um manipulador do bloco function-try-block de um construtor, o programa é mal formado.

Norma C ++, cláusula 15.3, parágrafo 16:

A exceção que está sendo tratada é relançada se o controle atingir o final de um manipulador do bloco function-try de um construtor ou destruidor. Caso contrário, uma function retorna quando o controle atinge o final de um manipulador para o bloco try-function (6.6.3). Fluir do final de um bloco function-try-block é equivalente a um retorno sem valor; isso resulta em um comportamento indefinido em uma function de retorno de valor (6.6.3).


Referências:
Dê uma olhada nisso deve ler o recurso aqui para mais detalhes e explicações.

Function-try-block é útil principalmente em construtores, porque não há outra maneira de capturar exceções na lista de boot. Nos destruidores, é preciso ter cuidado ao retornar no bloco catch, porque a exceção será automaticamente lançada novamente. (E em bom design destruidores não deve jogar.) Em funções normais esse recurso não é útil. Editar: um artigo antigo, mas ainda assim bom: http://drdobbs.com/184401316

Poderia também citar a especificação … Ou pelo menos um rascunho .

Artigo 15 (4):

Um function-try-block associa um manipulador-seq com o inicializador-ctor , se presente, e a instrução composta . Uma exceção lançada durante a execução da instrução composta ou, para construtores e destruidores, durante a boot ou destruição, respectivamente, dos subobjects da class, transfere o controle para um manipulador em um function-try-block da mesma maneira que uma exceção lançada durante a execução de um try-block transfere o controle para outros manipuladores.

(Aqui o manipulador-seq é o material depois da catch e a compound-statement é o corpo da function.)

Portanto, a “function try block” em um construtor ou destrutor captura exceções lançadas pelos inicializadores-ctor e pela construção ou destruição de sub-objects.

Em uma function diferente de um construtor ou destruidor, é o mesmo que simplesmente envolver o corpo da function. (Bem, tanto quanto eu posso discernir lendo a especificação.)

Recurso interessante e novo para mim. Obrigado por trazê-lo.

O exemplo “algo diferente” coloca o processamento da lista inicializadora dentro do escopo do bloco try.