Partilhar via


Aviso do compilador (nível 4) C4866

O compilador 'file(line_number)' não pode impor ordem de avaliação da esquerda para a direita para chamada para operator_name

Observações

A partir de C++17, os operandos dos operadores ->*, [], >>e << devem ser avaliados na ordem da esquerda para a direita. Há dois casos em que o compilador é incapaz de garantir esta ordem:

  • quando uma das expressões do operando é um objeto passado por valor ou contém um objeto passado por valor, ou

  • quando compilado usando /clr, e um dos operandos é um campo de um objeto ou um elemento de matriz.

O compilador emite o aviso C4866 quando não pode garantir a avaliação da esquerda para a direita. Esse aviso só é gerado se /std:c++17 ou mais tarde for especificado, pois o requisito de ordem da esquerda para a direita desses operadores foi introduzido no C++17.

Este aviso está desativado por padrão; você pode usar /Wall ou /wN4866 para habilitá-lo na linha de comando como um aviso de nível N ou usar #pragma aviso em seu arquivo de origem. Para obter mais informações, consulte Avisos do compilador que estão desativados por padrão.

Este aviso foi introduzido no Visual Studio 2017 versão 15.9 como resultado do trabalho de conformidade do compilador para o padrão C++17. Código que compilado sem avisos em versões do compilador antes do Visual Studio 2017 versão 15.9 agora pode gerar C4866. Para obter informações sobre como desativar avisos introduzidos em uma versão específica do compilador ou posterior, consulte Avisos do compilador por versão do compilador.

Para resolver esse aviso, primeiro considere se a avaliação da esquerda para a direita dos elementos do operador é necessária, como quando a avaliação dos elementos pode produzir efeitos colaterais dependentes da ordem. Em muitos casos, a ordem em que os elementos são avaliados não tem um efeito observável.

Se a ordem de avaliação deve ser da esquerda para a direita, considere se você pode passar os elementos por const referência. Essa alteração elimina o aviso no exemplo de código a seguir.

Example

Este exemplo gera C4866 e mostra uma maneira de corrigi-lo:

// C4866.cpp
// compile with: /w14866 /std:c++17

class HasCopyConstructor
{
public:
    int x;

    HasCopyConstructor(int x) : x(x) {}
    HasCopyConstructor(const HasCopyConstructor& h) : x(h.x) { }
};

int operator->*(HasCopyConstructor a, HasCopyConstructor b) { return a.x + b.x; }

// This version of operator->* does not trigger the warning:
// int operator->*(const HasCopyConstructor& a, const HasCopyConstructor& b) { return a.x + b.x; }

int main()
{
    HasCopyConstructor a{ 1 };
    HasCopyConstructor b{ 2 };

    a->*b;        // C4866 for call to operator->*
};