2017-01-26 17 views
12

Próbowałem zamienić dwie zmienne przy użyciu std::tie() według następującego kodu (jestem świadomy std::swap, właśnie próbowałem tego z ciekawości):Różne zachowanie przy próbie zamiany dwóch zmiennych za pomocą {} i std :: make_pair()

#include <iostream> 
#include <tuple> 

using std::cin; using std::tie; 
using std::cout; using std::endl; 
using std::make_pair; 

int main() { 
    int a = 2, b = 10; 
    cout << "Before Swapping using {}" << endl; 
    cout << "a: " << a << " b: " << b < <endl; 
    tie(a, b) = {b, a}; 
    cout << "After Swapping using {}" << endl; 
    cout << "a: " << a << " b: " << b << endl; 

    a = 2, b = 10; 
    cout << "Before Swapping using make_pair()" << endl; 
    cout << "a: " << a << " b: " << b << endl; 
    tie(a, b) = make_pair(b, a); 
    cout << "After Swapping using make_pair()" << endl; 
    cout << "a: " << a << " b: " << b << endl;  

    return 0; 
} 

I skompilowałem go przy użyciu g++ test.cpp -std=c++11 -o test.

Ale wyjście było to:

Before Swapping using {} 
a: 2 b: 10 
After Swapping using {} 
a: 10 b: 10 
Before Swapping using make_pair() 
a: 2 b: 10 
After Swapping using make_pair() 
a: 10 b: 2 

Więc moje pytanie jest, ponieważ możemy napisać {a, b} zamiast pisać std::make_pair(a, b) spędzaj (C++ 11 i dalsze), dlaczego te dwie wersje podając inny wyjście?

Domyślam się, że następująca linia

std::tie(a, b) = {b, a}; 

nie robi parę iz jakiegoś powodu tylko mutacji wartość a. Ale nie jestem pewien.

+0

wygląda jak niezdefiniowane zachowanie ... 'a' jest ustawione na wartość' b', a następnie zaktualizowane 'a' jest zapisywane w' b' ... Problem z punktem sekwencji. –

+0

@ Jarod42 daje odpowiedź poniżej. Masz rację, że możesz skonstruować parę za pomocą {}, ale kompilator musi wiedzieć, że to właśnie budujesz. –

Odpowiedz

5

tworzy std::tuple<int&, int&>, natomiast std::make_pair tworzy std::pair<int, int>.

Zastanów się, co stanie się z std::pair<int&, int&>. Zasadniczo przypisuje jedną ze zmiennych drugiej, a następnie próbuje przypisać drugą do pierwszej. Jest to równoważne z wykonaniem a = b; b = a; lub b = a; a = b;.

+0

Nie tworzy "pary ", tworzy 'krotkę '. – Barry

13

tie(a, b) = {b, a};

użyje std::tuple<int&, int&> operator = (std::tuple<int&, int&>&&). i nie std::tuple<int&, int&> operator = (std::tuple<int, int>&&) zgodnie z oczekiwaniami.

std::tie(a, b) jest std::tuple<int&, int&>.
std::tuple ma kilka operator =, ale tylko opłacalne z (nie wpisane) {a, b} to zadanie kopii/krok.

3

wystarczy użyć make_tuple

std::tie(a, b) = std::make_tuple(b, a); 

to samo a = b lub b = a;

Powiązane problemy