Trả về con trỏ thông minh theo giá trị.
Như bạn đã nói, nếu bạn trả lại bằng tham chiếu, bạn sẽ không tăng số lượng tham chiếu một cách chính xác, điều này sẽ mở ra nguy cơ xóa nội dung nào đó vào thời điểm không thích hợp. Điều đó một mình nên là đủ lý do để không trở lại bằng cách tham khảo. Giao diện nên mạnh mẽ.
Mối quan tâm về chi phí hiện nay là nhờ vào return value optimization (RVO), vì vậy bạn sẽ không phải chịu một chuỗi gia tăng hoặc giảm dần hoặc tương tự như vậy trong trình biên dịch hiện đại. Vì vậy, cách tốt nhất để trả lại một shared_ptr
là chỉ cần quay trở lại theo giá trị:
shared_ptr<T> Foo()
{
return shared_ptr<T>(/* acquire something */);
};
Đây là cơ hội RVO dead-rõ ràng cho trình biên dịch C++ hiện đại. Tôi biết một thực tế là trình biên dịch Visual C++ thực hiện RVO ngay cả khi tất cả các tối ưu hóa được 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à hồ sơ và thử nghiệm.)
Nếu bạn vẫn không bị thuyết phục, Dave Abrahams có số an article làm cho đối số trả về theo giá trị. Tôi tái tạo một đoạn trích ở đây; Tôi khuyên bạn nên đọc toàn bộ bài viết:
Hãy trung thực: mã sau làm bạn cảm thấy thế nào?
std::vector<std::string> get_names();
...
std::vector<std::string> const names = get_names();
Thẳng thắn, mặc dù tôi nên biết rõ hơn, điều đó khiến tôi lo lắng. Về nguyên tắc, khi get_names()
trả về, chúng tôi phải sao chép số vector
trong số string
giây. Sau đó, chúng tôi cần sao chép lại khi chúng tôi khởi tạo names
và chúng tôi 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 nhiều phân bổ bộ nhớ N + 1 và toàn bộ truy cập dữ liệu không thân thiện với bộ đệm ẩn> khi nội dung chuỗi được sao chép.
Thay vì đối đầu mà loại lo lắng, tôi đã thường rơi trở lại trên pass-by-reference để tránh 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, phương pháp này là xa lý tưởng.
- Mã này tăng 150%
- Chúng tôi đã phải thả
const
-ness bởi vì chúng ta đang biến đổi tên.
- lập trình viên Như 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 đối với lý do về bằng cách phá hoại minh bạch tham chiếu và lý luận equational.
- 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 để làm hỏng mã của chúng tôi 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à nếu bạn không sử dụng C++ 0x).
Tôi không biết rằng tôi có thể nói RVO làm cho câu hỏi tranh luận kể từ khi trở bằng cách tham khảo decidedly làm RVO không thể. –
@CrazyEddie: Đúng vậy, đó là một trong những lý do tôi khuyên OP trả lại theo giá trị. –
Quy tắc RVO có được phép theo tiêu chuẩn hay không, vượt qua các quy tắc về đồng bộ hóa/xảy ra trước các mối quan hệ, được đảm bảo theo tiêu chuẩn? –