2016-01-26 34 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