Share via


Upozornění kompilátoru (úroveň 4) C4866

Kompilátor 'file(line_number)' nemusí vynutit pořadí vyhodnocení zleva doprava pro volání operator_name

Poznámky

Počínaje jazykem C++17 musí být operandy operátorů ->*, [] >>a << musí být vyhodnoceny v pořadí zleva doprava. Existují dva případy, kdy kompilátor nemůže zaručit toto pořadí:

  • pokud jeden z výrazů operandu je objekt předaný hodnotou nebo obsahuje objekt předaný hodnotou, nebo

  • při kompilaci pomocí /clr a jeden z operandů je pole objektu nebo prvku pole.

Kompilátor vygeneruje upozornění C4866, pokud nemůže zaručit vyhodnocení zleva doprava. Toto upozornění se vygeneruje pouze v případě, že /std:c++17 je zadáno nebo novější, protože požadavek na pořadí zleva doprava byl zaveden v jazyce C++17.

Toto upozornění je ve výchozím nastavení vypnuté; Můžete použít /Wall nebo /wN4866 k povolení na příkazovém řádku jako upozornění na úroveň N nebo použít #pragma upozornění ve zdrojovém souboru. Další informace najdete v tématu Upozornění kompilátoru, která jsou ve výchozím nastavení vypnutá.

Toto upozornění bylo zavedeno v sadě Visual Studio 2017 verze 15.9 v důsledku shody kompilátoru pro standard C++17. Kód kompilovaný bez upozornění ve verzích kompilátoru před sadou Visual Studio 2017 verze 15.9 teď může generovat C4866. Informace o tom, jak zakázat upozornění zavedená v konkrétní verzi kompilátoru nebo novější, naleznete v tématu Upozornění kompilátoru podle verze kompilátoru.

Chcete-li toto upozornění vyřešit, nejprve zvažte, zda je nezbytné vyhodnocení prvků operátoru zleva doprava, například při vyhodnocení prvků může vést k nežádoucím účinkům závislým na pořadí. V mnoha případech pořadí, ve kterém jsou prvky vyhodnoceny, nemá pozorovatelný účinek.

Pokud musí být pořadí vyhodnocení zleva doprava, zvažte, jestli místo toho můžete předat prvky odkazem const . Tato změna eliminuje upozornění v následující ukázce kódu.

Příklad

Tato ukázka vygeneruje C4866 a ukazuje způsob, jak ji opravit:

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