Udostępnij za pośrednictwem


Ostrzeżenie kompilatora (poziom 4) C4866

Kompilator "file(line_number)" może nie wymuszać kolejności oceny od lewej do prawej w celu wywołania operator_name

Uwagi

Począwszy od języka C++17, operandy operatorów ->*, [], >>i << muszą być oceniane w kolejności od lewej do prawej. Istnieją dwa przypadki, w których kompilator nie może zagwarantować tej kolejności:

  • gdy jedno z wyrażeń operandu jest obiektem przekazywanym przez wartość lub zawiera obiekt przekazywany przez wartość lub

  • podczas kompilowania przy użyciu /clr, a jeden z operandów jest polem obiektu lub elementu tablicy.

Kompilator emituje ostrzeżenie C4866, gdy nie może zagwarantować oceny od lewej do prawej. To ostrzeżenie jest generowane tylko w przypadku /std:c++17 określenia lub nowszego, ponieważ w języku C++17 wprowadzono wymaganie dotyczące kolejności od lewej do prawej tych operatorów.

To ostrzeżenie jest domyślnie wyłączone; Można użyć /Wall lub /wN4866, aby włączyć go w wierszu polecenia jako ostrzeżenie poziomu N lub użyć #pragma ostrzeżenie w pliku źródłowym. Aby uzyskać więcej informacji, zobacz Ostrzeżenia kompilatora, które są domyślnie wyłączone.

To ostrzeżenie zostało wprowadzone w programie Visual Studio 2017 w wersji 15.9 w wyniku pracy kompilatora dla standardu C++17. Kod kompilowany bez ostrzeżeń w wersjach kompilatora przed wygenerowaniem C4866 programu Visual Studio 2017 w wersji 15.9. Aby uzyskać informacje na temat wyłączania ostrzeżeń wprowadzonych w określonej wersji kompilatora lub nowszej, zobacz Ostrzeżenia kompilatora według wersji kompilatora.

Aby rozwiązać to ostrzeżenie, najpierw należy rozważyć, czy konieczna jest ocena elementów operatora od lewej do prawej, na przykład w przypadku oceny elementów, które mogą powodować skutki uboczne zależne od kolejności. W wielu przypadkach kolejność oceniania elementów nie ma zauważalnego efektu.

Jeśli kolejność oceny musi być od lewej do prawej, rozważ, czy zamiast tego możesz przekazać elementy przy użyciu const odwołania. Ta zmiana eliminuje ostrzeżenie w poniższym przykładzie kodu.

Przykład

Ten przykład generuje kod C4866 i pokazuje sposób jego naprawy:

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