2012-01-24 44 views
16

Tôi chỉ mất một số lượng thời gian không đủ thời gian với một lỗi biên dịch trong Visual Studio. Tôi đã chưng cất mã vào ví dụ nhỏ có thể biên dịch bên dưới và thử nó trên IdeOne và gặp lỗi tương tự mà bạn có thể thấy here.Tại sao mã này đang cố gắng gọi hàm tạo bản sao?

tôi tự hỏi tại sao đoạn code sau cố gắng gọi B(const B&) thay vì 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; 
} 

Tôi không xác định một cách rõ ràng bất kỳ nhà xây dựng, vì vậy B(std::move(binst)) nên gọi trình biên dịch tạo ra B(B&&), không có?

Khi tôi thay đổi B để

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

Nó biên dịch tốt. Tại sao điều này? Nó sẽ vô cùng bất tiện nếu điều này không thể được sửa từ lớp cơ sở vì tôi có một lớp mẫu sử dụng vị trí mới và di chuyển các hàm tạo như ví dụ, và nó sẽ yêu cầu mọi lớp không thể sao chép được (không và chắc chắn không phải là một yêu cầu để sử dụng với lớp mẫu của tôi) để có một hàm tạo di chuyển được định nghĩa rõ ràng.

+0

Có trình biên dịch được tạo B (B &&) không? C++ 11 của tôi vẫn còn một chút gỉ. Và B của bạn (B &&) có cần khởi tạo A (A &&) không? – CashCow

+0

@CashCow có, tất cả những gì bạn làm là di chuyển từng thành viên (nếu điều đó sai thì tôi đang nhìn bạn, Kerrek SB ':)') –

+0

Biên dịch tốt trên GCC 4.6, GCC 4.7 và Clang 3.0. –

Trả lời

15

Nếu bạn đang sử dụng Visual Studio 2010 hoặc 2012, hãy lưu ý: trình biên dịch thực hiện không tự động tạo ra các hàm tạo di chuyển cho bạn. Điều đó không được thực hiện. Vì vậy, bạn cần tự viết chúng.

+1

Cần lưu ý rằng các chi tiết của khi một nhà xây dựng di chuyển nên được ngầm định nghĩa là mặc định đã thay đổi gần cuối của quá trình tiêu chuẩn hóa và vc2010 đã được khoảng trước đó. Ngoài ra, vc2010 không hỗ trợ '= delete', mà làm cho nó khó khăn để nói về sự phù hợp của các nhà xây dựng di chuyển :) – avakar

+0

Đó là nghiêm trọng gây phiền nhiễu. Tôi mong chờ VS11. Cảm ơn. –

+4

@Seth Carnegie: VC11 sẽ không tạo ra phương thức khởi động tự động ... http: //blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx "Các tham chiếu Rvalue v3.0 bổ sung các quy tắc mới để tự động tạo các nhà xây dựng di chuyển và di chuyển các toán tử gán trong các điều kiện nhất định. Điều này sẽ không được thực hiện trong VC11, sẽ tiếp tục để theo dõi hành vi của VC10 không bao giờ tự động tạo ra các nhà thầu di chuyển/di chuyển các toán tử gán. " –

5

Bạn phải đối mặt với lỗi trình biên dịch. Tiêu chuẩn nói rằng B nhận được một hàm khởi tạo di chuyển ngầm định và được xác định; tất cả các điều kiện của 12.8 (9) được đáp ứng (tức là B không có một nhà xây dựng bản sao được khai báo rõ ràng, sao chép-chuyển nhượng, vv, và các nhà xây dựng di chuyển sẽ không ngầm được tuyên bố deleted).

+1

Tôi đoán đây là những gì tôi nhận được để sử dụng VS, một trình biên dịch được viết giữa các tiêu chuẩn. Cảm ơn. –

Các vấn đề liên quan