2015-09-27 15 views
6

Từ những gì tôi hiểu, std::forward<T>(x) tương đương với static_cast<T&&>(x).C++ std :: forward <T> vs static_cast <T>

Nhưng từ những gì tôi thấy, static_cast<T>(x) dường như làm điều tương tự, như có thể thấy trong code

Câu hỏi của tôi sau do đó là lý do tại sao std::forward<T> được thực hiện như static_cast<T&&>(x), và không static_cast<T>(x), nếu cả hai có cùng hiệu ứng?

+1

Bạn đã không thử với 'int &'. – Quentin

+0

@Quentin Trong trường hợp đó, nó luôn trả về một giá trị. – Mikrosaft

+0

'static_cast ' sẽ tạo bản sao giá trị –

Trả lời

10

Vì chuyển tiếp hoàn hảo cho phép chuyển cả hai tham chiếu giá trị r rtham chiếu giá trị l. Này được thực hiện thông qua reference collapsing:

T = int --> T&& = int&& 
T = int& --> T&& = int& && = int& 
T = int&& --> T&& = int&& && = int&& 

Trong ví dụ của bạn với static_cast<T> bạn chỉ cần mất tài liệu tham khảo r-giá trị. Nó hoạt động tốt cho các kiểu nguyên thủy (vì việc chuyển int thường sao chép giá trị đăng ký CPU), nhưng khủng khiếp đối với các kiểu phức tạp vì nó dẫn đến việc tạo đối tượng tạm thời thông qua các ctors sao chép.

+0

Tôi vừa kiểm tra nó, và trên thực tế, gọi hàm tạo bản sao cho giá trị của rvalue. Nhưng tại sao? Tôi đọc rằng nếu chúng ta gọi func() với một rvalue, T được suy ra là int &&, vì vậy static_cast (x) sẽ trở thành static_cast (x). Vậy tại sao nó tạo bản sao? – Mikrosaft

+2

'static_cast ' có thể trả về một tham chiếu: câu trả lời ở trên ngụ ý nó không thể. Bạn có thể làm rõ rằng vấn đề chỉ xảy ra trong một "trường hợp"? – Yakk

+0

@Microsaft: không, 'T' không thể được suy ra thành' int && ', nó chỉ có thể là' int' hoặc 'int &'. – myaut

2

Nếu T&& là một tài liệu tham khảo rvalue, sau đó T là một giá trị, sau đó static_cast<T> làm cho một bản sao không phải là một tài liệu tham khảo rvalue.

Bản sao đó sẽ liên kết với tham chiếu rvalue (giống như tham chiếu), nhưng sao chép/di chuyển ctors có thể được gọi không cần thiết, và nó không phải là một ứng cử viên cho elision.

static_cast<T&&> trong khi chờ đợi, chỉ cần truyền tới tham chiếu rvalue.

Chúng giống hệt nhau.

0

Tôi đồng ý với Yakk, nhưng điều đó còn tệ hơn thế.

void foo(const std::vector<int> &vec); 

template<typename T> 
void callFoo(T &&data) 
{ 
    foo(static_cast<T>(data)); 
} 

int main() 
{ 
    callFoo(std::vector<int>{/*...*/}); 
} 

Điều này sẽ luôn tạo bản sao. Vectơ là không phải được di chuyển vì data, dưới dạng biểu thức, là một loại giá trị theo loại std::vector<int>, mặc dù loại được thay thế là std::vector<int>&&. Lưu ý rằng Tstd::vector<int>, không phải std::vector<int> &&. Đạo đức của câu chuyện: Sử dụng thư viện chuẩn, nó làm điều đúng và tên forward cũng nắm bắt ý định tốt hơn nhiều so với static_cast<something>.

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