使用函数返回整数并(可能)修改基指针会导致返回数组的预期成员时出现不良行为。
这与相当古老的旧代码有关;使用容器的现代选项将解决问题(请不用告诉我!),但是我想指出这一点,并询问在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.
};
答案 0 :(得分:5)
在C ++ 17之前,ArrayPointer
和dosomething()
之间的求值顺序是不确定的。 (因此,在C ++ 14中它“有效” 的事实是通过“机会” 来实现的。)
在C ++ 17中,ArrayPointer
应该在dosomething()
之前求值。
请参阅Order of evaluation,规则17。