2014-12-15 19 views
5

Tôi xin lỗi nếu tiêu đề câu hỏi không chính xác - nhưng tôi gặp khó khăn khi hiểu những gì đang diễn ra ở đây.Giảm dần giá trị để rvalue với lỗi tự động

Hãy xem xét các lớp sau đây:

struct foo { 
    foo(foo&); 
}; 

Sau đây không có lỗi:

void func(foo& f) { 
    foo bar{f}; 
} 

Tuy nhiên, khi tôi sử dụng auto:

void func(foo& f) { 
    auto bar = foo{f}; 
} 

tôi nhận được (gcc):

test.cpp: In function ‘void func(foo&)’: 
test.cpp:6:21: error: no matching function for call to ‘foo::foo(foo)’ 
test.cpp:6:21: note: candidate is: 
test.cpp:2:5: note: foo::foo(foo&) 
test.cpp:2:5: note: no known conversion for argument 1 from ‘foo’ to ‘foo&’ 

(vang)

test.cpp:6:10: error: no matching constructor for initialization of 'bar' 
    auto bar = foo{f}; 
     ^ ~~~~~~ 
test.cpp:2:5: note: candidate constructor not viable: expects an l-value for 1st argument 
    foo(foo&); 
    ^

ai đó có thể vui lòng giải thích lý do tại sao đây là một lỗi?

Cảm ơn!

Chỉnh sửa: Nó hoạt động nếu tôi thêm một hàm tạo bản sao vào foo. Tuy nhiên, tôi đã ấn tượng rằng việc khai báo biến + lời gọi rõ ràng đến hàm tạo ở bên phải của cú pháp '=' được xử lý đặc biệt và không phải là một bản sao xây dựng mà là khởi tạo trực tiếp.

Trả lời

8
auto bar = foo{f}; 

auto được khấu trừ là foo. Sau đó, định nghĩa của bạn là tương đương với

foo bar = foo{f}; 

Bạn đang cố gắng để tạo ra một đối tượng kiểu foo đó là sao chép khởi tạo với các prvalue foo{f}.

Vấn đề là hàm tạo bản sao của foo có tham chiếu không phải là const lvalue làm tham số của nó, không thể liên kết với một giá trị. Ngoài ra, hàm tạo di chuyển không được định nghĩa hoàn toàn khi bạn có một hàm tạo bản sao do người dùng khai báo. Do đó không có hàm tạo nào có thể lấy foo{f} và trình biên dịch đưa ra một thông báo lỗi.

+0

Trình biên dịch có phát ra cuộc gọi đến trình tạo bản sao không? Tôi đã theo ấn tượng rằng trình biên dịch sẽ coi đây là khởi tạo trực tiếp. –

+0

Nhập Ahh trên Android chậm và dường như không có cách nào để xóa câu trả lời cũng như –

+0

@RobertMason Trình biên dịch có thể bỏ cuộc gọi đến một trình tạo bản sao không có tác dụng phụ, nhưng trình tạo bản sao vẫn phải gọi. – Oktalist

3
auto bar = foo{f}; 

Đây là khởi tạo sao chép và theo ngữ nghĩa của nó, yêu cầu sự hiện diện của hàm tạo bản sao. Tuy nhiên, hàm tạo bản sao của foo lấy tham chiếu không const và tham chiếu không phải const không thể bị ràng buộc tạm thời, đó là foo{f}.

Giải pháp là tạo một hàm tạo bản sao có tham chiếu const, như các hàm tạo bản sao thường làm.

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