Nếu bạn muốn hiệu suất, vượt qua giá trị nếu bạn đang lưu trữ nó.
Giả sử bạn có một hàm gọi là "chạy cái này trong luồng UI".
std::future<void> run_in_ui_thread( std::function<void()> )
chạy một số mã trong luồng "ui", sau đó báo hiệu future
khi hoàn thành. (Hữu ích trong các khung UI, trong đó luồng UI là nơi bạn có nghĩa vụ phải làm rối với các thành phần UI)
Chúng tôi có hai chữ ký chúng tôi đang xem xét:
std::future<void> run_in_ui_thread( std::function<void()> ) // (A)
std::future<void> run_in_ui_thread( std::function<void()> const& ) // (B)
Bây giờ, chúng tôi có thể sử dụng những điều này như sau:
run_in_ui_thread( [=]{
// code goes here
} ).wait();
cái này sẽ tạo ra một bao đóng ẩn danh (lambda), xây dựng std::function
nó, chuyển nó đến run_in_ui_thread
hàm, sau đó đợi nó chạy xong trong luồng chính.
Trong trường hợp (A), std::function
được xây dựng trực tiếp từ lambda của chúng tôi, sau đó được sử dụng trong run_in_ui_thread
. Lambda là move
d vào std::function
, vì vậy bất kỳ trạng thái di chuyển nào được thực hiện một cách hiệu quả vào nó.
Trong trường hợp thứ hai, một tạm thời std::function
được tạo ra, lambda được move
đưa vào đó, sau đó tạm thời std::function
được sử dụng bởi tham chiếu trong run_in_ui_thread
.
Cho đến nay, rất tốt - hai người họ thực hiện giống hệt nhau. Ngoại trừ việc run_in_ui_thread
sẽ tạo một bản sao của đối số chức năng của nó để gửi đến luồng ui để thực thi! (nó sẽ trở lại trước khi nó được thực hiện với nó, vì vậy nó không thể chỉ sử dụng một tham chiếu đến nó). Đối với trường hợp (A), chúng tôi chỉ đơn giản là move
các std::function
thành lưu trữ lâu dài của nó. Trong trường hợp (B), chúng tôi buộc phải sao chép std::function
.
Cửa hàng đó làm cho việc đi qua giá trị tối ưu hơn. Nếu có bất kỳ khả năng nào bạn đang lưu trữ một bản sao của std::function
, vượt qua giá trị. Mặt khác, một trong hai cách là tương đương nhau: nhược điểm duy nhất của giá trị phụ là nếu bạn đang sử dụng cùng std::function
một phương pháp cồng kềnh và có một phương thức phụ sau khi sử dụng phương pháp khác. Chặn rằng, a move
sẽ hiệu quả như a const&
.
Bây giờ, có một số khác biệt khác giữa hai chủ yếu là đá nếu chúng ta có trạng thái dai dẳng trong std::function
.
Giả sử rằng std::function
lưu trữ một số đối tượng với a operator() const
, nhưng nó cũng có một số mutable
thành viên dữ liệu mà nó sửa đổi (thật thô lỗ!).
Trong std::function<> const&
trường hợp, các mutable
thành viên dữ liệu được sửa đổi sẽ truyền ra khỏi lệnh gọi hàm. Trong std::function<>
trường hợp, họ sẽ không.
Đây là một trường hợp góc tương đối lạ.
Bạn muốn đối xử std::function
như bạn sẽ làm với bất kỳ loại di chuyển nặng, có thể nặng khác. Di chuyển là rẻ, sao chép có thể tốn kém.
sizeof(std::function)
không nhiều hơn2 * sizeof(size_t)
, đó là kích thước nhỏ nhất mà bạn từng xem xét để tham khảo const.