Nó được sử dụng để thường được khuyến cáo thực hành tốt nhất 1 để sử dụng vượt qua bởi ref const cho tất cả các loại , trừ BUILTIN loại ( char
, int
, double
, vv), cho vòng lặp và cho các đối tượng chức năng (lambdas, các lớp học bắt nguồn từ std::*_function
).
Điều này đặc biệt đúng trước sự tồn tại của ngữ nghĩa di chuyển . Lý do rất đơn giản: nếu bạn chuyển qua giá trị, một bản sao của đối tượng phải được tạo và ngoại trừ các đối tượng rất nhỏ, điều này luôn đắt hơn so với việc chuyển tham chiếu.
Với C ++ 11, chúng tôi đã đạt được ngữ nghĩa di chuyển . Tóm lại, di chuyển ngữ nghĩa cho phép, trong một số trường hợp, một đối tượng có thể được truyền qua giá trị bởi giá trị mà không cần sao chép nó. Đặc biệt, đây là trường hợp khi đối tượng mà bạn đang đi qua là một rvalue .
Trong chính nó, di chuyển một đối tượng vẫn ít nhất là tốn kém như chuyển qua tham chiếu. Tuy nhiên, trong nhiều trường hợp, một hàm sẽ sao chép bên trong một đối tượng - nghĩa là nó sẽ sở hữu đối số. 2
Trong những tình huống này, chúng ta có sự đánh đổi (đơn giản hóa) sau:
- Chúng ta có thể vượt qua đối tượng bằng cách tham chiếu, sau đó sao chép nội bộ.
- Chúng ta có thể vượt qua đối tượng theo giá trị.
Truyền thông qua giá trị, vẫn còn khiến đối tượng bị sao chép, trừ khi đối tượng là một giá trị. Trong trường hợp của một giá trị, thay vào đó, đối tượng có thể được di chuyển, do đó, trường hợp thứ hai đột nhiên không còn là bản sao, sau đó di chuyển, nhưng di chuyển, sau đó (có khả năng) di chuyển lại một lần nữa.
Đối với các đối tượng lớn mà thực hiện nhà xây dựng di chuyển thích hợp (ví dụ như vectơ, dây ...), trường hợp thứ hai là sau đó bao la hiệu quả hơn là người đầu tiên. Do đó, nên sử dụng pass by value nếu hàm có quyền sở hữu đối số và nếu loại đối tượng hỗ trợ di chuyển hiệu quả .
Một ghi chú lịch sử:
Trong thực tế, bất kỳ trình biên dịch hiện đại nào cũng có thể tìm ra khi truyền theo giá trị là đắt và chuyển đổi cuộc gọi để sử dụng const ref nếu có thể.
Về lý thuyết. Trong thực tế, trình biên dịch không thể luôn thay đổi điều này mà không phá vỡ giao diện nhị phân của hàm. Trong một số trường hợp đặc biệt (khi chức năng được nội tuyến), bản sao sẽ thực sự bị xóa nếu trình biên dịch có thể tìm ra rằng đối tượng ban đầu sẽ không bị thay đổi thông qua các hành động trong chức năng.
Nhưng nói chung, trình biên dịch không thể xác định điều này và sự ra đời của ngữ nghĩa di chuyển trong C ++ đã khiến việc tối ưu hóa này ít liên quan hơn nhiều.
1 Ví dụ trong Scott Meyers, C ++ hiệu quả .
2 Điều này đặc biệt thường đúng đối với các nhà xây dựng đối tượng, có thể lấy các đối số và lưu trữ chúng bên trong để trở thành một phần của trạng thái của đối tượng được xây dựng.