Tôi đã đọc this answer và tác giả đề cập đến boost best practices mà nói:C++ phân bổ shared_ptr với C++ 11 (std :: shared_ptr): Vẫn còn xấu để khởi tạo shared_ptr thành một biến tạm thời?
Tránh sử dụng shared_ptr giấu tên là tạm thời để tiết kiệm gõ; để xem tại sao này là nguy hiểm, hãy xem xét ví dụ sau:
void f(shared_ptr<int>, int);
int g();
void ok() {
shared_ptr<int> p(new int(2));
f(p, g());
}
void bad() {
f(shared_ptr<int>(new int(2)), g());
}
Chức năng ok sau phương châm để lá thư, trong khi cấu trúc xấu shared_ptr tạm thời tại chỗ, thừa nhận khả năng của một rò rỉ bộ nhớ . Vì các đối số hàm được đánh giá theo thứ tự không xác định, có thể để int (2) mới được đánh giá đầu tiên, g() thứ hai và chúng tôi không bao giờ có thể nhận được đối với hàm tạo shared_ptr nếu g ném ngoại lệ. <...>
Vấn đề an toàn ngoại lệ nêu trên cũng có thể được loại bỏ bằng sử dụng các chức năng nhà máy make_shared hoặc allocate_shared quy định tại tăng/make_shared.hpp. Các chức năng của nhà máy này cũng cung cấp lợi ích hiệu quả bằng cách hợp nhất phân bổ.
Tôi đoán tôi sẽ bắt đầu sử dụng make_shared
, nhưng tôi đã tự hỏi liệu lời khuyên này vẫn áp dụng cho C++ 11 shared_ptr
. Tôi hỏi bởi vì tôi không thực sự hiểu rõ lý do tại sao nó là một ném g()
sẽ ngăn chặn các ctor nhận được gọi.
Tôi không thể yêu cầu một lời giải thích tốt hơn, nó chỉ thực sự bất ngờ (với tôi) rằng "thứ tự giải nén" của một cái gì đó như thế này sẽ không phải lúc nào cũng giống nhau. Ngoài ra, tôi vẫn chưa có cơ hội để có được một sự hiểu biết đúng đắn về các tham chiếu rvalue. –
@StevenLu: tham chiếu rvalue không liên quan gì đến điều đó. Tôi vừa sử dụng 'auto &&' để nắm bắt kết quả của 'g()' để nó có thể được chuyển tiếp đúng khi nó đến thời gian để gọi hàm. Nó không có gì để làm với thứ tự của các hoạt động. Ngoài ra, thứ tự có thể sẽ giống nhau ... chỉ không * qua * trình biên dịch. –
Ah. Thấy chưa, tôi đã thấy '&&', biết đó là "điều tôi chưa hiểu", nên tôi không điều tra thêm. Nhưng bây giờ tôi thấy đoạn mã (giả) này minh họa cách mà trình biên dịch có thể tạo mã để tạo ra 'g()' ** sau khi ** phân bổ int, và cả hai dòng đầu tiên có thể ngược lại trật tự (trong trường hợp này mọi thứ sẽ ổn). –