Trả lại con trỏ thông minh theo giá trị.
Như bạn đã nói, nếu bạn trả lại nó bằng cách tham chiếu, bạn sẽ không tăng số lượng tham chiếu đúng cách, điều này dẫn đến nguy cơ xóa nội dung nào đó vào thời điểm không thích hợp. Chỉ điều đó thôi cũng đủ lý do để không quay lại bằng cách tham khảo. Các giao diện phải mạnh mẽ.
Mối quan tâm về chi phí ngày nay được tranh cãi nhờ tối ưu hóa giá trị trả về (RVO), vì vậy bạn sẽ không phải chịu một trình tự tăng-tăng-giảm hoặc tương tự như vậy trong các trình biên dịch hiện đại. Vì vậy, cách tốt nhất để trả về a shared_ptr
là chỉ cần trả về theo giá trị:
shared_ptr<T> Foo()
{
return shared_ptr<T>(/* acquire something */);
};
Đây là một cơ hội RVO rõ ràng cho các trình biên dịch C ++ hiện đại. Tôi biết thực tế là các trình biên dịch Visual C ++ triển khai RVO ngay cả khi tất cả các tối ưu hóa bị tắt. Và với ngữ nghĩa di chuyển của C ++ 11, mối quan tâm này thậm chí còn ít liên quan hơn. (Nhưng cách duy nhất để chắc chắn là lập hồ sơ và thử nghiệm.)
Nếu bạn vẫn chưa thuyết phục, Dave Abrahams có một bài báo đưa ra lập luận cho việc trả về theo giá trị. Tôi sao chép một đoạn mã ở đây; Tôi thực sự khuyên bạn nên đọc toàn bộ bài viết:
Hãy trung thực: đoạn mã sau đây khiến bạn cảm thấy thế nào?
std::vector<std::string> get_names();
...
std::vector<std::string> const names = get_names();
Thành thật mà nói, mặc dù tôi nên biết rõ hơn, nó khiến tôi lo lắng. Về nguyên tắc, khi get_names()
trả về, chúng ta phải sao chép một vector
trong số string
s. Sau đó, chúng ta cần sao chép nó một lần nữa khi khởi tạo
names
và chúng ta cần hủy bản sao đầu tiên. Nếu có N string
s trong vectơ, mỗi bản sao có thể yêu cầu tối đa N + 1 phân bổ bộ nhớ và một loạt các truy cập dữ liệu không thân thiện với bộ nhớ cache> khi nội dung chuỗi được sao chép.
Thay vì đối mặt với loại lo lắng đó, tôi thường quay trở lại tham khảo qua để tránh các bản sao không cần thiết:
get_names(std::vector<std::string>& out_param );
...
std::vector<std::string> names;
get_names( names );
Thật không may, cách tiếp cận này là xa lý tưởng.
- Mã tăng 150%
- Chúng tôi đã phải bỏ
const
-ness vì chúng tôi đang biến đổi tên.
- Như các lập trình viên chức năng muốn nhắc nhở chúng ta, đột biến làm cho mã phức tạp hơn để suy luận bằng cách làm suy yếu tính minh bạch của tham chiếu và suy luận cân bằng.
- Chúng tôi không còn có ngữ nghĩa giá trị nghiêm ngặt cho tên.
Nhưng có thực sự cần thiết phải xáo trộn mã của chúng ta theo cách này để đạt được hiệu quả không? May mắn thay, câu trả lời hóa ra là không (và đặc biệt là không nếu bạn đang sử dụng C ++ 0x).