2014-11-07 15 views
5

Kompilowanie następującego kodu z kodem 3.5.0 i gcc 4.9.1 powoduje błąd w ostatniej instrukcji.Dlaczego lista wiersza-inicjalizowanego zachowuje się inaczej w wywołaniu funkcji w porównaniu z wywołaniem konstruktora?

#include <iostream> 

struct Foo { Foo(int x, int y) { std::cout << "Foo(int = " << x << ", int = " << y << ")" << std::endl; } }; 

void bar(int x, int y) { std::cout << "bar(int = " << x << ", int = " << y << ")" << std::endl; } 

int main() 
{ 
    Foo({}, {}); // Foo(int = 0, int = 0) 
    Foo({1}, {2}); // Foo(int = 1, int = 2) 
    Foo({1, 2}); // Foo(int = 1, int = 2) 

    bar({}, {}); // bar(int = 0, int = 0) 
    bar({1}, {2}); // bar(int = 1, int = 2) 
    bar({1, 2}); // error: no matching function for call to 'bar' <<< Why? <<< 
} 

Dlaczego Foo({1, 2}) porządku podczas bar({1, 2}) nie jest?

Szczególnie byłoby wspaniale dowiedzieć się o racjonalności.

+3

Domyślam się, 'Foo ({1,2})' tworzy tymczasowy obiekt Foo i wywołuje konstruktor kopiowania . – Borgleader

+0

@Borgleader Dziękuję, to ma sens! :-) – precarious

+0

Komentarz do @Borgleader jest poprawny - z {1, 2} możesz utworzyć tymczasowy obiekt Foo, ale tylko wtedy, gdy oczekuje się Foo. W rzeczywistości nie można przekazać wielu parametrów, aby z tym działać. –

Odpowiedz

6

Foo({1,2}) tworzy tymczasowy obiekt Foo i wywołuje konstruktor kopiowania.

Zobacz ten zmodyfikowany przykład z konstruktora kopii usunięcia: http://coliru.stacked-crooked.com/a/6cb80746a8479799

błędy go z:

main.cpp:6:5: note: candidate constructor has been explicitly deleted 
    Foo(const Foo& f) = delete; 
+0

Ale czy nie był konstruktem kopiowania niejawnie wygenerowanym w oryginalnym przykładzie? Po co to usuwać i powodować inne kompilacje? To nie wyjaśnia, dlaczego 'bar' nie może być wywołany; i chodzi przede wszystkim o argumenty baru, zobacz ten [sposób naprawiania kompilacji] (http://coliru.stacked-crooked.com/a/2b8f6fee6244c251) –

+0

@NorahAttkins Tęskniłeś za sednem. Chodzi o to, że lista inicjalizacyjna nie przekazuje 2 wzorców do konstruktora (który zakładał, że OP i zastanawiał się, dlaczego nie zadziała w wywołaniu funkcji, które również zajmuje 2 int), generuje obiekt tymczasowy i wywołuje skopiować konstruktora. Usunięcie go pokazało, że wywołano konstruktora kopiowania. – Borgleader

+0

Nie, nie było; Zobacz ten [przykład] (http://coliru.stacked-crooked.com/a/7314848093d2987a) Jeśli usunę połączenie do 'Foo ({1, 2})' program nadal nie skompiluje się, wywołując 'bar' bez kiedykolwiek wspominam o konstruktach skasowanych kopii. Wezwanie do 'bar' nigdy nie stworzyło tymczasowego obiektu' Foo' –

1

Linia

bar({1, 2}); 

faktycznie przechodzi w funkcji bar, tymczasowy obiekt z wpisz

<brace-enclosed initializer list> // it's made clear in the comments that brace initializers have no type 

i nie ma możliwości przekonwertowania tego tymczasowego obiektu na typ pierwszego argumentu, który jest int. Zatem error

nie może konwertować <brace-enclosed initializer list> do int dla argumentu 1 do

void bar(int, int) 
+0

Nie, to nie jest poprawne. Lista wzmocnionych-init nie ma typu. – Columbo

+0

@ Columbo Czy [masz pewność] (http://coliru.stacked-crooked.com/a/7dbfd72283b52c55)? –

+1

@NorahAttkins [Początek stężonego nie ma typu] (http://www.youtube.com/watch?v=wQxj20X-tIU&list=UUMlGfpWw-RUdWX_JbLCukXg#t=1792) – Borgleader

Powiązane problemy