2016-01-26 32 views
3

我在C++上做了一些模拟,并且遇到了一个奇怪的问题。我有以下函数返回的双重载体:未定义的行为

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 

,它工作得很好,所以这增强了我的hypotesis。

而且我注意到一个调试怪事:试图弄清楚发生了什么事(固定代码之前)的时候,我看着均值和方差的调试通过的价值观和他们都错了。但是,当我运行程序时,只有意思是错误的(我已经尝试了很多次,而且总是这样:调试时都是错误的,在运行时意味着错误和方差是正确的)。 这里发生了什么?

的Java问题:好,这个问题我已经见过,真是烦我,因为经常在Java中,缩短的事情,我没有直接上,将返回该函数定义新的对象,但使用的方法对象(如本例中)。虽然,我从来没有遇到任何问题。我一直在做事情无意中(幸运的是)?或者仅仅是在Java中没有这样的行为存在,因为应该返回对象的函数实际上返回指向它们的指针,而真正的对象总是在堆中(并且在没有引用它们时被垃圾回收)?

希望你能澄清我的疑惑!

+0

请添加'// do things'代码。我猜测你没有正确地初始化一些东西。 –

+0

无论如何,你为什么要返回'vector ',而不是使用输出参数表示均值和方差? –

+0

@AndyTurner这不会是更好的C++。 –

回答

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>

+0

谢谢!这是我当时猜测的。另外,感谢您提供关于使用结构或对的建议。我有一个关于这个问题:你宁愿使用一个结构或一对,因为它似乎_redundant_使用一个固定大小的对象的向量?或者这种方法有更多优点吗? – Harnak

+0

这里的大图是关于你的代码实际返回的类型_says_。它不会说“我会返回一个均值和方差,其中平均值是第一位的,并且总是会有两个值”。它实际上是说“我会返回任意数量的值,或者根本不返回任何值”。如果你养成了明确表达其意图的代码的习惯,那么从长远来看,你会发现自己犯的错误更少。 – paddy

+0

非常感谢您的提示:) – Harnak