2016-12-01 14 views
4

This code compilesのstd ::ネクタイ:: make_tupleバージョンが優先されなければならないが、私は思ったんだけど

#include <iostream> 
#include <tuple> 
using namespace std; 

tuple<int, int, int> return_tuple1() { 
    int a = 33; 
    int b = 22; 
    int c = 31; 
    return tie(a, b, c); 
} 

tuple<int, int, int> return_tuple2() { 
    int a = 33; 
    int b = 22; 
    int c = 31; 
    return make_tuple(a, b, c); 
} 

int main() { 
    auto a = return_tuple1(); 
    auto b = return_tuple2(); 
    return 0; 
} 

機能以来のはstd::tieを使用して任意の問題があってはならない値でタプルを返して右? (ぶら下がっている参照はありません)

答えて

1

std::tieには十分注意してください。 tieを返すことは、リファレンスを返すことと論理的に等価であり、すべての警告にそれが付属しています。

は論理的には、これらの3つは等価です。

int& foo(); 
std::reference_wrapper<int> foo(); 
std::tuple<int&> foo(); 

と、この:

:それはこれらのいずれかを生成するので

int a = 10; 
return std::ref(a); 

int a = 10; 
return std::tie(a); 

がこれに相当します

std::tuple<int&> 

この例では、戻り値の暗黙の変換によって保存されます。しかし、戻り値のタイプをautoに置き換えると、論理エラーが表示されます。

#include <iostream> 
#include <tuple> 
using namespace std; 

auto return_tuple1() { // function name is now lying 
    int a = 33;   // it should be return_chaos() 
    int b = 22; 
    int c = 31; 
    return tie(a, b, c); 
} 

auto return_tuple2() { 
    int a = 33; 
    int b = 22; 
    int c = 31; 
    return make_tuple(a, b, c); 
} 

int main() { 
    auto a = return_tuple1(); // uh-oh... 

    auto b = return_tuple2(); 

    std::get<0>(a); // undefined behaviour - if you're lucky you'll get a segfault at some point. 
    std::get<0>(b); // perfectly ok 
    return 0; 
} 
8

std::tieはあなたの考えをしません。
std::tie、何実際に起こることであるreturn_tuple1()にので、渡された要素に参照tupleを返す:

tuple<int, int, int> return_tuple1() { 
    int a = 33; 
    int b = 22; 
    int c = 31; 
    return std::tuple<int&,int&,int&>(a,b,c); 
} 

その後、戻り型tuple<int, int, int>自体にstd::tuple<int&,int&,int&>からを構築します。

今、コンパイラかもしれないこの構造を最適化するが、私はそれに賭けないだろう。そのタスクには適切なツールであるので、std::make_tupleを使用してください。

+0

また、std :: make_tupleはコードの意図をよりよく表しています。 'std :: tie'を呼び出すコードを見て、それを' tuple'に格納すると、バグだと思うでしょう。 – SirGuy

1

tuple2がより効率的でなければなりません。 tietupleを作成しますが、tieについては覚えておくべきことは、タイプArgs...のタプルを作成するのではなく、戻り値の型とタプルが一致しないタプルArgs&...を作成するということです。つまり、結び付けられたタプルから戻り値のタプルにコピーする必要があります。

2番目の例では、戻り値の型と同じ型のタプルを返すので、直接返すことができます。そこにコピーする必要はありません。

関連する問題