Partilhar via


Aviso do compilador (nível 4) C4866

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

Comentários

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

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

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

O compilador emite um aviso C4866 quando não é capaz de garantir a avaliação da esquerda para a direita. Esse aviso é gerado apenas se /std:c++17 ou uma versão posterior forem especificados, já que o requisito de ordem da esquerda para direita desses operadores foi introduzido no C++17.

Esse 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 o aviso #pragma no arquivo de origem. Para obter mais informações, confira Avisos do compilador desativados por padrão.

Esse 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. O código 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 desabilitar 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, considere primeiro se a avaliação da esquerda para a direita dos operandos é necessária; por exemplo, quando a avaliação dos elementos pode produzir efeitos colaterais dependentes da ordem. Em muitos casos, a ordem na qual os operandos são avaliados não tem efeitos observáveis.

Se a ordem da avaliação precisar ser da esquerda para a direita, considere se não é possível passar os elementos por referência const. Essa alteração elimina o aviso no exemplo de código a seguir.

Exemplo

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->*
};