VS中的C ++ 17会导致c ++ 14中不存在的变量(重新)评估错误

时间:2019-04-25 20:18:59

标签: c++ visual-studio-2017

使用函数返回整数并(可能)修改基指针会导致返回数组的预期成员时出现不良行为。

这与相当古老的旧代码有关;使用容器的现代选项将解决问题(请不用告诉我!),但是我想指出这一点,并询问在C ++ 17下行为是否是故意的,与C ++ 14及以下版本相反。

代码如下:

// dosomething() returns an integer.
// ArrayPointer is a class member
somememberfunction(args)
{
   ...
   return ArrayPointer[dosomething()];
}

问题产生于以下事实:dosomething()将更改ArrayPointer,并且使用ArrayPointer的旧值代替新值(在C ++ 17下,而不在C ++ 14下)。 解决方法是定义一个中间变量:

const int index=dosomething();
return ArrayPointer[index];

问题是:是否有解释(取决于标准),或者将其视为错误,而不是从我的角度来看只是不良行为?

PS:根据要求填写(er C)代码,注意非必要部分,省略变量声明:

struct BKPRArray    // struct for applying meteocorrection
{
    double *findprarray(const char *bks)
    {
    // check earlier allocations (NR)
    for (int n = 0; n < arrays; n++)
        if (!_stricmp(this->bk[n], bks))
        {
            if (!PRarray[n]) PRarray[n] = (NUMTYPE*)calloc(FL_alloced, sizeof(NUMTYPE));
            return PRarray[n];
        }
    // combined return statement will fail under C++17 by using the old value of PRarray.
    // This MAY be caused by order of evaluation, rule 17: https://en.cppreference.com/w/cpp/language/eval_order
    // allocate and prepare (preparation code omitted) a new array.
    //return PRarray[addarray(bks, defaultMeteoCorrection)];
    const auto index = addarray(bks, defaultMeteoCorrection);
    return PRarray[index];  // zet factor op +20%, want bk niet specifiek vermeld bij input.
    }
    ....
    int addarray(const char *bks, const double fact = defaultMeteoCorrection)
    {
        PRarray = (double**)realloc(PRarray, (arrays + 1) * sizeof(*PRarray));
        if (FL_alloced) PRarray[arrays] = (NUMTYPE*)calloc(FL_alloced, sizeof(NUMTYPE));
        else PRarray[arrays] = NULL;
        ...
        return arrays++;
    }
    ....
private:
    double **PRarray;   // etc.
};

1 个答案:

答案 0 :(得分:5)

在C ++ 17之前,ArrayPointerdosomething()之间的求值顺序是不确定的。 (因此,在C ++ 14中它“有效” 的事实是通过“机会” 来实现的。)

在C ++ 17中,ArrayPointer应该在dosomething()之前求值。

请参阅Order of evaluation,规则17。