编译器警告(等级 4)C4866
“file(line_number)”编译器可能不会在对 operator_name 的调用中强制执行从左到右计算顺序
注解
从 C++17 开始,运算符“->*”、“,”、“[]”和 << 的操作数必须按从左到右的顺序计算>>。 在以下两种情况下,编译器无法保证此顺序:
当编译器无法保证从左到右计算时,它将发出警告 C4866。 只有在指定 /std:c++17
或更高版本时才会生成此警告,因为这些运算符的从左到右顺序要求是在 C++17 中引入的。
此警告默认处于关闭状态;可以使用 /Wall 或 /wN4866 在命令行上启用它(作为等级 N 警告),或者在源文件中使用 #pragma warning。 有关详细信息,请参阅默认关闭的编译器警告。
由于 C++17 标准的编译器一致性工作,Visual Studio 2017 版本 15.9 中引入了此警告。 在 Visual Studio 2017 版本 15.9 之前的编译器版本中没有编译时警告的代码现在可能生成 C4866。 有关如何禁用特定编译器版本或更高版本中引入的警告的信息,请参阅由编译器版本引发的编译器警告。
若要解决此警告,首先考虑运算符元素的从左到右计算是否是必需的,例如,元素的计算可能会生成依赖于顺序的副作用的情况。 在许多情况下,元素计算的顺序不会有什么明显的影响。
如果计算顺序必须是从左到右,则考虑是否可以改为通过 const
引用来传递元素。 此更改可消除以下代码示例中的警告。
示例
此示例将生成 C4866,并演示修复方法:
// 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->*
};