未定义的行为

时间:2016-01-26 00:37:00

标签: java c++ undefined-behavior

我正在对C ++进行一些模拟,而且我遇到了一个奇怪的问题。我有以下函数返回double的向量:

vector<double> processSimulation(int Q){
//do things
vector<double> output;
output.push_back(mean);
output.push_back(variance);
return output;
}

总的来说,我有以下几点:

//define Q
vector<double>::iterator it = processSimulation(Q).begin();
double mean = *it;
double variance = *(it+1);

问题在于我得到了一个错误的平均数(e-305的数字)和一个正确的方差数。 我试图自己解释这种行为,我认为这可能是由于和未定义的行为引起的,因为迭代器指向函数中的旧向量,现在已超出范围而不再存在。我对么? 可能我很幸运,方差是正确的,因为它可能也是错误的。

我将代码更改为

vector<double> output = processSimulation(Q);
vector<double>::iterator it = output.begin();
//same as before

它运作得很好,所以这加强了我的创作。

另外我注意到了一个调试器怪异:当试图弄清楚发生了什么时(在修复代码之前),我通过调试查看了均值和方差的值,但它们都是错误的。虽然,当我运行程序时,只有平均值是错误的(我已经尝试了很多次并且它总是:调试时都错了,运行时意味着错误和方差正确)。 这里发生了什么?

Java问题:好吧,我遇到的这个问题真的很烦我,因为通常在Java中,为了缩短事情,我没有定义新对象但是直接使用了方法在将返回该对象的函数上(如本例所示)。虽然,我从来没有遇到过任何问题。我是不是一直在做无意中(幸运的是)?或者只是Java中的没有这样的行为存在,因为应该返回对象的函数实际上返回指向它们的指针,而真正的对象总是在堆中(并且当它们存在时会被包围)。没有提及他们)?

希望你能澄清我的怀疑!

1 个答案:

答案 0 :(得分:7)

这是人们在关于链接 rvalues 的调用时懒得而不是将结果存储在局部变量中时犯下的一个非常常见的错误。

vector<double>::iterator it = processSimulation(Q).begin();

在上文中,您的processSimulation(Q)来电返回vector<double>。然后,您将获得一个迭代器到vector的开头并存储它。既然结果向量不再在范围内,它就会被销毁。这留下了一个悬垂的迭代器。

现在你开始使用它了。请记住,迭代器包含有效信息,但它指向不再存在的对象:

double mean = *it;            // undefined behaviour
double variance = *(it+1);    // undefined behaviour

认为它有点像这样:

vector<double>::iterator it;
{
    vector<double> result = processSimulation(Q);
    it = result.begin();
}
double mean = *it;    // boom

当您更改代码以将返回值存储在局部变量中时,将定义行为,前提是向量在您使用迭代器的整个时间内保持在范围内。

所以这是正确的(除了你问题上与C ++风格相关的评论):

vector<double> output = processSimulation(Q);
vector<double>::iterator it = output.begin();
double mean = *it;
double variance = *(it+1);

但你可以轻易地抛弃迭代器并使用数组索引运算符:

double mean = output[0];
double variance = output[1];

您可能需要考虑返回自己的封装此信息的结构,而不是向量。或者至少切换到使用std::pair<double, double>