2016-09-15 82 views
11

我試圖避免在我的函數中輸出參數。舊的功能是:函數返回由向量組成的元組

void getAllBlockMeanError(
    const vector<int> &vec, vector<int> &fact, vector<int> &mean, vector<int> &err) 

這裏vec的輸入參數,factmeanerr是輸出參數。我試着組輸出參數添加一個元組:

tuple< vector<int>, vector<int>, vector<int> > 
            getAllBlockMeanErrorTuple(const vector<int> &vec) 
{ 
    vector<int> fact, mean, err; 
    //.... 
    return make_tuple(fact, mean, err); 
} 

現在,我可以調用新的函數:

tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec); 

它看起來更清潔我。雖然我有一個問題,tie(fact, mean, err)的平等分配是如何工作的?它是否做了深層複製或移動?由於factmeanerr裏面的getAllBlockMeanErrorTuple將被銷燬,我希望它是做一個動作而不是深拷貝。

+0

我還不能肯定,但我認爲,作爲寫它會複製載體。如果將矢量移動到'make_tuple()'中,則應移動它們。 – Andy

+5

我會使用'struct Result {vector 其實;矢量的意思;矢量犯錯; };而不是元組更好地命名getter。 – Jarod42

回答

12

您函數簽名是tuple< vector<int>, vector<int>, vector<int> >,這是一個臨時的,元素有資格被感動,所以

std::tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec) 

應該將指派factmeanerr

下面是一個示例程序,讓你看到自己(demo):

#include <iostream> 
#include <vector> 
#include <tuple> 

struct A 
{ 
    A() = default; 
    ~A() = default; 
    A(const A&) 
    { 
     std::cout << "Copy ctor\n"; 
    } 
    A(A&&) 
    { 
     std::cout << "Move ctor\n"; 
    } 
    A& operator=(const A&) 
    { 
     std::cout << "Copy assign\n"; 
     return *this; 
    } 
    A& operator=(A&&) 
    { 
     std::cout << "Move assign\n"; 
     return *this; 
    } 
}; 

std::tuple<A, A> DoTheThing() 
{ 
    A first; 
    A second; 
    return std::make_tuple(first, second); 
} 

int main() 
{ 
    A first; 
    A second; 
    std::tie(first, second) = DoTheThing(); 
} 

輸出:

拷貝構造函數
拷貝構造函數
移動分配
移動分配

請注意,函數必須創建向量的副本,以返回tuple,這可能不是您想要的。您可能需要的元素std::movestd::make_tuple

return make_tuple(std::move(fact), std::move(mean), std::move(err)); 

Here's the same example as above, but with std::move used in make_tuple

注意,使用C++ 17的結構化綁定,您可以如何使用std::tie都忘了,靠更上auto(感謝@ Yakk):

auto[fact, mean, err] = getAllBlockMeanErrorTuple(vec); 

的鐺(3.8.0)和gcc(6.1.0)不支持它尚未在C++ 17標準的早期實現,但它似乎還有一些C支持郎4.0.0:Demo(謝謝,@Revolver_Ocelot)

你會發現,用結構化的綁定更改輸出:

移動男星
移動男星

表明它們利用copy-elision,可以節省額外的移動操作。

+1

'auto [fact,mean,err] = getAllBlockMeanErrorTuple(vec);' – Yakk

+1

@Yakk:那不是C++ 17嗎? – AndyG

+0

是的,但我認爲值得一提,至少順帶一提。 – Yakk

11
std::tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec); 

會做移動分配。

但正如評論

return make_tuple(fact, mean, err); 

會做一份提到的,你可以解決與:

return make_tuple(std::move(fact), std::move(mean), std::move(err)); 
+0

至少提到C++ 17結構化綁定!我們距離它只有幾個月的時間了! (對於這裏的限定值) – Yakk

+0

謝謝Jarod42。 –