2016-07-13 22 views
8

Trong cuộc thảo luận, chúng tôi đã có here Tôi đang chơi đùa với các functors đi qua. C++ STL chuyển functors thành các giá trị (xem trong std::for_each, std::find_if, std::transform)Tại sao functor templated được chuyển thành giá trị và không chuyển tiếp tham chiếu

Vì vậy, khai báo của tôi sẽ như thế này.

template<typename F> 
void call_me(F f) 
{ 
    f(); 
} 

Bây giờ, gọi có thể có thể gọi ftor 's copy constructor (nó sẽ rất có thể được copy elided, vì vậy không phải là trường hợp). Nhưng ftor f{}; call_me(f); sẽ dẫn đến sao chép. Nếu ftor có dữ liệu lớn, có thể đó là vấn đề.

Chúng tôi sẽ cải thiện nó bằng cách chuyển nó dưới dạng tham chiếu const (void call_me(const F& f)) để loại bỏ bản sao không cần thiết. Điều này là miễn là ftor::operator()const. Nếu không, cuộc gọi đến call_me sẽ dẫn đến lỗi biên dịch (mất const vòng loại).

Vì vậy, tại sao phải bận tâm với tham chiếu const, chỉ sử dụng tham chiếu (void call_me(F& f)). Điều này là tốt, nhưng nó sẽ không hoạt động đối với trường hợp đầu tiên là vì việc đưa giá trị r vào (tham chiếu giá trị l) không hợp lệ là không hợp lệ.

Khai báo f làm tham chiếu chuyển tiếp (void call_me(F&& f)) dường như hoạt động trong mọi trường hợp. Tôi tin rằng, điều này hoạt động nhờ tham chiếu sụp đổ.

Vì vậy, tại sao functors templated không được chuyển như tham chiếu chuyển tiếp trong các chức năng từ STL?

Trả lời

9

tại sao các functors được tô khuôn không được chuyển thành tham chiếu giá trị r trong các hàm từ STL?

Trước hết, chúng sẽ là tài liệu tham khảo , không tham chiếu rvalue.

Điều đó nói rằng, với nhiều câu hỏi "tại sao" về thiết kế ngôn ngữ nói chung, câu trả lời có thể đơn giản là: bởi vì chưa có ai đề xuất thay đổi này (xem how to submit a proposal). Tôi nghi ngờ một lượng lớn các đối tượng hàm được chuyển vào các thuật toán thư viện chuẩn là lambdas, không quốc tịch hoặc cực kỳ rẻ. Hơn nữa, nếu bạn có một đối tượng đắt tiền như vậy bạn luôn có thể quay trong nó vào một giá rẻ copyable cho các mục đích của thuật toán:

call_me(std::ref(huge_object)); 

Cuối cùng, một số trong những thuật toán dựa vào thông qua các chức năng này các đối tượng xung quanh để giúp đỡ khác . Nếu thuật toán chỉ đơn giản giả định rằng đối tượng hàm là "miễn phí" để sao chép, điều này làm cho nó dễ dàng để mã. Nếu chúng ta giới thiệu khả năng giá trị ở đây, điều này sẽ thêm một lớp câu hỏi khác cần được giải quyết - chúng ta có vượt qua tham chiếu xung quanh không? Điều gì về các đối tượng chức năng với ref-đủ điều kiện operator()?

Một số kết hợp những điều trên có thể giải thích tại sao, ví dụ, nó vẫn còn:

template <class InputIt, class UnaryPredicate> 
InputIt find_if(InputIt, InputIt, UnaryPredicate); 

và không

template <class InputIt, class UnaryPredicate> 
InputIt find_if(InputIt, InputIt, UnaryPredicate&&); 
Các vấn đề liên quan