编译器警告(等级 4)C4868

“file(line_number)”编译器可能不会在用大括号括起的初始化表达式列表中强制执行从左到右计算顺序

用大括号括起的初始化表达式列表中的元素将按从左到右的顺序进行计算。 在两种情况下,编译器无法保证此顺序:第一种是当某些元素是由值传递的对象时;第二种是在使用 /clr 编译时,其中一些元素是对象的字段或是数组元素。 当编译器无法保证从左到右计算时,它将发出警告 C4868。

此警告还可能来自于为 Visual Studio 2015 Update 2 执行的编译器一致性工作。 在 Visual Studio 2015 Update 2 之前编译的代码现在可能生成 C4868。

默认情况下,此警告处于关闭状态。 使用 /Wall 可激活此警告。

若要解决此警告,首先考虑初始化表达式列表元素的从左到右计算是否是必需的,例如,元素的计算可能会生成依赖于顺序的副作用的情况。 在许多情况下,元素计算的顺序不会有什么明显的影响。

如果计算顺序必须从左到右,请考虑是否可以改为通过 const 引用来传递元素。 此类更改可消除以下代码示例中的警告。

示例

此示例将生成 C4868,并演示修复方法:

// C4868.cpp
// compile with: /c /Wall
#include <cstdio>

class HasCopyConstructor
{
public:
    int x;

    HasCopyConstructor(int x): x(x) {}

    HasCopyConstructor(const HasCopyConstructor& h): x(h.x)
    {
        printf("Constructing %d\n", h.x);
    }
};

class TripWarning4868
{
public:
    // note that taking "HasCopyConstructor" parameters by-value will trigger copy-construction.
    TripWarning4868(HasCopyConstructor a, HasCopyConstructor b) {}

    // This variation will not trigger the warning:
    // TripWarning4868(const HasCopyConstructor& a, const HasCopyConstructor& b) {}
};

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

    // the warning will indicate the below line, the usage of the braced initializer list.
    TripWarning4868 warningOnThisLine{a, b};
};