Se tivermos três funções (foo, bar e baz) que são compostas assim ...
foo(bar(), baz())
Existe alguma garantia pelo padrão C ++ de que a barra será avaliada antes do baz?
Se tivermos três funções (foo, bar e baz) que são compostas assim ...
foo(bar(), baz())
Existe alguma garantia pelo padrão C ++ de que a barra será avaliada antes do baz?
Respostas:
Não, não existe essa garantia. Não é especificado de acordo com o padrão C ++.
Bjarne Stroustrup também diz isso explicitamente na seção 6.2.2 "The C ++ Programming Language" 3ª edição, com alguns argumentos:
Um código melhor pode ser gerado na ausência de restrições na ordem de avaliação da expressão
Embora tecnicamente isso se refira a uma parte anterior da mesma seção que diz que a ordem de avaliação das partes de uma expressão também não é especificada, ou seja,
int x = f(2) + g(3); // unspecified whether f() or g() is called first
Não há ordem especificada para bar () e baz () - a única coisa que o padrão diz é que ambos serão avaliados antes de foo () ser chamado. Do padrão C ++, seção 5.2.2 / 8:
A ordem de avaliação dos argumentos não é especificada.
bar
, a seguir a linha 1 de baz
, a linha 2 de bar
etc.), o que também é bom. :-)
De [5.2.2] chamada de função,
A ordem de avaliação dos argumentos não é especificada. Todos os efeitos colaterais das avaliações de expressão de argumento têm efeito antes que a função seja inserida.
Portanto, não há garantia de que bar()
será executado antes baz()
, apenas que bar()
e baz()
será chamado antes foo
.
Observe também em [5] Expressões que:
exceto onde indicado [por exemplo, regras especiais para
&&
e||
], a ordem de avaliação dos operandos de operadores individuais e subexpressões de expressões individuais, e a ordem em que os efeitos colaterais ocorrem, não é especificada.
então, mesmo que você perguntasse se bar()
será executado antes baz()
em foo(bar() + baz())
, a ordem ainda não foi especificada.
&
, &&
garante a avaliação da esquerda para a direita: o segundo operando não é avaliado se o primeiro operando for false
."
C ++ 17 especifica a ordem de avaliação para operadores que não foram especificados até C ++ 17. Veja a pergunta Quais são as garantias de ordem de avaliação introduzidas pelo C ++ 17? Mas observe sua expressão
foo(bar(), baz())
ainda tem ordem de avaliação não especificada.
Em C ++ 11, o texto relevante pode ser encontrado em 8.3.6 Argumentos padrão / 9 (Ênfase minha)
Os argumentos padrão são avaliados sempre que a função é chamada. A ordem de avaliação dos argumentos da função não é especificada . Conseqüentemente, os parâmetros de uma função não devem ser usados em um argumento padrão, mesmo se não forem avaliados.
O mesmo palavreado também é usado pelo padrão C ++ 14 e pode ser encontrado na mesma seção .
Como outros já apontaram, a norma não fornece nenhuma orientação sobre a ordem de avaliação para este cenário específico. Essa ordem de avaliação é então deixada para o compilador, e o compilador pode ter uma garantia.
É importante lembrar que o padrão C ++ é realmente uma linguagem para instruir um compilador na construção de código de montagem / máquina. O padrão é apenas uma parte da equação. Onde o padrão é ambíguo ou é especificamente definido pela implementação, você deve recorrer ao compilador e entender como ele traduz as instruções C ++ em verdadeira linguagem de máquina.
Portanto, se a ordem de avaliação for um requisito, ou pelo menos importante, e ser compatível com compilador cruzado não é um requisito, investigue como seu compilador acabará por juntar isso, sua resposta pode estar aí. Observe que o compilador pode mudar sua metodologia no futuro