2015-09-09 49 views
3

我是編程新手,我正在使用本書研究C++編程語言:編程原理和使用C++的練習。我今天來到這裏,因爲在第8章的結尾,筆者着重功能,提出了一種鍛鍊邀請學生去思考更好的解決一個問題:從函數返回值:參考vs結構

編寫發現功能的最小矢量參數的最大元素,並計算均值和中值。不要使用全局變量。返回一個包含結果的struct或通過引用參數傳遞它們。你更喜歡哪一個返回幾個值?爲什麼?

現在,通常我不會定義一個函數來執行多個動作,但在這種情況下,我必須創建一個函數並考慮如何返回多個值。我的第一個方法是創建一個函數,引用參數是這樣的:

void my_func(
    vector<double>& numbers, 
    double& min, 
    double& max, 
    double& mean, 
    double& median 
); 

但隨着寫程序怎麼回事,我開始認爲這個解決方案中使用的參數太多,也許提出了另一種解決方案(使用struct)會更好。你將如何使用struct來解決這個問題?你如何從函數中返回多個值?

+0

您不會從函數返回多個值,這是不可能的。相反,您返回*一個*結構實例,其中包含多個成員(例如'min','max'等成員)。 –

+0

只要有用和可能,請使用[封裝](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))。在這裏它是可能的和有用的,因此你應該在答案中使用一個結構(例如stats)。 – HelloWorld

+1

如果你正在使用C++ 11,你可能想看看[std :: tuple](http://en.cppreference.com/w/cpp/utility/tuple) –

回答

5

使用struct這個問題很簡單:定義的返回類型爲struct,並使用它,就像這樣:

struct stats { 
    double min; 
    double max; 
    double mean; 
    double median; 
}; 
stats my_func(vector<double>& numbers) { 
    stats res; 
    ... 
    res.min = ... 
    res.max = ... 
    res.mean = ... 
    res.median = ... 
    return res; 
} 

這裏的代價是,以換取有一個更簡單的函數簽名時,你的函數的用戶需要逐一提取他們想要的元素。

但是,如果結構非常複雜並且複製成本變得過於昂貴,怎麼辦?

與您的函數的「有效負載」CPU時間相比,複製所需的極端大小的結構變得過於昂貴。最重要的是,C++優化器通過採用copy elisionreturn value optimization策略,當你這樣做減少了複製費用:

stats s = my_func(numbers); 

struct變得如此巨大,你不想複製,結合像這兩種方法這樣的:

void my_func(vector<double>& numbers, stats& res); 
+0

@PoojaNilangekar謝謝,它是一個很好的編輯。不幸的是,它自動被拒絕了,因爲我自己正在編輯答案。感謝您收到此複製粘貼錯誤! – dasblinkenlight

+0

從我學習的基礎知識中知道,當函數返回值時,會創建一個return_value的副本。但是如果結構非常複雜並且複製的成本變得太高,那麼呢? –

+1

@pieroborrelli隨着移動語義和複製的機會是好的,你不會真的做一個副本。特別是如果你從函數返回初始化一個變量。 – NathanOliver

0

聲明struct

struct stats { 
    double min; 
    double max; 
    double mean; 
    double median; 
}; 

然後

stats my_func(vector<double>& numbers); 

功能會是這樣

stats my_func(vector<double>& numbers) { 
    stats return_value; 

    // Fill in the structure 

    return return_value; 
} 
0

那麼你只返回一個結構。

struct res { 
    double min; 
    double max; 
    double mean; 
    double median; 
}; 

res my_func(vector<double>& numbers) { 
    res result; 
    // do stuff, put result in in result.min etc 

    return result; 
} 

其它可以以類似的方式來完成:

void my_func(vector<double>& numbers, 
      res& result) 
{ 
    // the same code except no return value 

    return; 
} 

現在在你的任務的問題(我不回答 - 因爲它是你喜歡什麼問題),我想提到技術差異是什麼。

當返回一個結構就意味着你可能會創建result結構的臨時副本(也可能導致兩個對象res一個呼叫者和一個my_func一起工作)。而另一種方法意味着你傳遞給函數基本上決定了結果的放置位置。有了「好」的實現,你可能會得到相同的代碼。

+0

隨着移動語義和複製的機會是好的,你不會真的做一個副本。特別是如果你從函數返回初始化一個變量。 – NathanOliver

+0

這個可能性已經發生了變化,我改變了它的形式「可能」到「可能」,以表明它現在不太可能。 – skyking