2013-06-06 62 views
10

Xin lỗi vì tiêu đề quá mơ hồ (do thiếu kỹ năng tiếng Anh của tôi). Vui lòng đề xuất một tiêu đề tốt hơn.Tại sao trình tạo bản sao không được gọi?

Vui lòng xem xét mã sau đây.

struct A { 
    typedef std::vector<double> State; 

    // template <class... Args> 
    // A(Args... args) 
    //  : a(args...) 
    // {} 

    template <class... Args> 
    A(Args&&... args) 
      : a(std::forward<Args>(args)...) 
    {} 

    A(const A&) = default; 
    A(A&&) = default; 

    State a; 
}; 

int main(){ 

    A a(3,2); 
    A b = a; // This line triggers an error!! 
} 

Gcc 4.8.0 thất bại trong việc biên dịch nó với các thông báo lỗi error: no matching function for call to 'std::vector<double>::vector(A&)' : a(std::forward<Args>(args)...).

Tôi không thể hiểu tại sao mã này sai. Theo tôi, trình biên dịch nên gọi hàm tạo bản sao trong dòng A b = a;.

Tuy nhiên, nếu tôi thay thế hàm tạo bằng trình nhận xét (chỉ đơn giản là lấy giá trị). Nó biên dịch. Hơn nữa, bây giờ các dòng cho các nhà xây dựng sao chép (và di chuyển) mặc định là không cần thiết. Điều gì xảy ra ở đây?

Trả lời

9

Trong C++ 11 có trình biên dịch tự động suy ra các thông số mẫu (như bạn phải làm gì với một constructor templated) và áp dụng && các loại tạo một tham chiếu phổ quát, phù hợp với bất kỳ loại nào với bất kỳ bằng cấp cv nào, cho dù đó là tham chiếu giá trị hoặc giá trị rvalue.

Vì vậy, trong trường hợp của bạn, bạn đang đi trong một A, và do đó Args... = A &, Args &&... = A & &&, đó là A & nhờ quy tắc tham khảo-sụp đổ, mà là một trận đấu tốt hơn so với const A &, vì trình biên dịch không phải thêm constness vào một biến không phải const.

+1

Ồ, tôi hiểu rồi. Cảm ơn lời giải thích rõ ràng. :) – Sungmin

3

Tôi nghĩ trong trường hợp này, hàm tạo mẫu là kết quả phù hợp hơn vì giá trị không phải là const. nếu bạn thay đổi a-const nó sẽ gọi các nhà xây dựng bản sao ...

const A a(3,2); 
A b = a; 
+0

Cảm ơn nếu tôi thêm một hàm tạo bản sao khác 'A (A &) = mặc định'. Nó biên dịch tốt. :) – Sungmin

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