2012-01-24 17 views
16

Po prostu spędziłem nadmierną ilość czasu, błądząc z błędem kompilacji w Visual Studio. Destylowałem kod do małego przykładu poniżej i próbowałem go na IdeOne i otrzymałem ten sam błąd, który można zobaczyć here.Dlaczego ten kod próbuje wywołać konstruktora kopiowania?

Zastanawiam się, dlaczego następujący kod próbuje zadzwonić B(const B&) zamiast B(B&&):

#include <iostream> 

using namespace std; 

class A { 
public: 
    A() : data(53) { } 
    A(A&& dying) : data(dying.data) { dying.data = 0; } 

    int data; 

private: 
    // not implemented, this is a noncopyable class 
    A(const A&); 
    A& operator=(const A&); 
}; 

class B : public A { }; 

int main() { 
    B binst; 

    char* buf = new char[sizeof(B)]; 

    B* bptr = new (buf) B(std::move(binst)); 

    cout << bptr->data << endl; 

    delete[] buf; 
} 

nie wyraźnie określa żadnych konstruktorów, więc B(std::move(binst)) powinien zadzwonić kompilator generowane B(B&&), nie?

Kiedy zmienić B do

class B : public A { 
public: 
    B() { } 
    B(B&&) { } 
}; 

To kompiluje grzywny. Dlaczego to?

Będzie bardzo niewygodne, jeśli nie można go naprawić z klasy bazowej, ponieważ mam klasę szablonów, która używa nowych miejsc i przenosi konstruktorów, takich jak przykład, i będzie wymagać każdej klasy, która nie jest kopiowalna (co jest nie, zdecydowanie nie powinno być wymogiem do użycia z moją klasą szablonów), aby mieć jawnie zdefiniowany konstruktor ruchu.

+0

Czy jest wygenerowany kompilator B (B &&)? Moje C++ 11 jest wciąż trochę zardzewiałe. I czy twoja B (B &&) musi zainicjować A (A &&)? – CashCow

+0

@CashCow tak, wszystko co robi to przesuwanie każdego członka (jeśli jest źle, to patrzę na ciebie, Kerrek SB ':)') –

+0

Kompiluje się dobrze na GCC 4.6, GCC 4.7 i Clang 3.0. –

Odpowiedz

15

Jeśli używasz Visual Studio 2010 lub 2012, informujemy: kompilator robi nie automatycznie generować ruch dla Ciebie konstruktorów. To nie zostało wdrożone. Musisz napisać je sam.

+1

Należy zauważyć, że szczegóły dotyczące tego, kiedy konstruktor ruchu ma być domyślnie zdefiniowany jako domyślny, zmieniły się pod koniec procesu standaryzacji, a vc2010 już wcześniej. Ponadto, vc2010 nie obsługuje '= delete', co utrudnia mówienie o zgodności konstruktorów ruchu :) – avakar

+0

To jest naprawdę denerwujące. Tęsknię za VS11. Dzięki. –

+4

@Seth Carnegie: VC11 nie wygeneruje automatycznie przenieść konstruktora albo ... http: //blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx "Odniesienia do wartości RV w wersji 3.0 dodają nowe reguły do ​​automatycznego generowania konstruktorów ruchu i przenoszenia operatorów przypisania w określonych warunkach.Nie będzie to realizowane w VC11, które będzie kontynuowane śledzić zachowanie VC10 polegające na tym, że nigdy nie generują automatycznie konstruktorów ruchu/operatorów przeniesienia. " –

5

Musisz zmierzyć się z błędem kompilatora. Standard mówi, że B otrzymuje domyślnie zadeklarowany i zdefiniowany konstruktor ruchu; spełnione są wszystkie warunki podane w 12.8 (9) (tj. B nie ma jawnie zadeklarowanego konstruktora kopii, przydziału kopiowania itd., a konstruktor ruchu nie zostanie domyślnie zadeklarowany jako deleted).

+1

Sądzę, że to jest to, co otrzymuję za używanie VS, kompilatora, który został napisany między-standardami. Dzięki. –

Powiązane problemy