2017-06-13 15 views
7

tôi đang làm việc với một cơ sở mã mà làm cho sử dụng rộng rãi trong những cú pháp sau:Tôi có nên sử dụng shared_ptr <Object> myObject = (shared_ptr <Object>) new Object() để truy cập các nhà thầu tư nhân không?

shared_ptr<Object> myObject = (shared_ptr<Object>) new Object(); 

tôi nhận thấy rằng tôi không thể truy cập constructors riêng với make_shared, nhưng shared_ptr<Object> myObject = (shared_ptr<Object>) new Object(); làm việc tốt. Tôi có nên sử dụng nó chỉ vì nó có vẻ hoạt động không? Có nguy hiểm gì không? Nó khác với make_shared như thế nào?

tôi biết câu trả lời trong this câu hỏi, mà làm cho sự so sánh giữa make_shared và:

std::shared_ptr<Object> p2(new Object("foo")); 

nhưng tôi đã không thể tìm thấy một tài liệu tham khảo cho các cú pháp Tôi đã xem qua. Nó khác, hay nó giống như trên?

+3

Dòng mã đầu tiên trông giống như dàn diễn viên kiểu 'C': xem (1) tại đây: http://en.cppreference.com/w/cpp/language/explicit_cast –

+1

Hãy xem tại đây: https://stackoverflow.com/questions/32168/c-cast-syntax-styles – zdan

Trả lời

10

make_shared phân bổ đối tượng trong cùng một khối bộ nhớ làm khối điều khiển. Điều này cải thiện khả năng kết hợp bộ nhớ cache và cắt giảm phân bổ.

Một cách để cho phép make_shared để làm điều này là phải có một tin thẻ trong lớp học của bạn, và một constructor nào mà tiêu thụ token.

class Object { 
private: 
    struct token_t{ private: token_t() {}; friend class Object; }; 
    static token_t token() { return {}; } 
    Object() = default; 
public: 
    Object(token_t):Object() {} 
}; 

bây giờ chúng tôi có thể make_shared<Object>(Object::token()).

Điều này cho chúng ta một phân bổ và không vi phạm quyền riêng tư của công trình vì chỉ những thứ có quyền truy cập vào các trường riêng tư Object mới có thể gọi hàm tạo đó. Tuy nhiên, họ có thể chuyển mã thông báo cho một chức năng khác (như make_shared) và đến lượt nó có thể gọi hàm khởi tạo được đề cập. Điều này làm việc với nhiều đối số, một cách tự nhiên.

Đối với cú pháp của bạn:

std::shared_ptr<Object> myObject = (std::shared_ptr<Object>) new Object(); 

(std::shared_ptr<Object>) new Object(); xây dựng đơn giản một cách rõ ràng shared_ptr<Object> từ new Object(). Nó tương đương với std::shared_ptr<Object>(new Object).

Sau đó, chúng tôi lấy giá trị này và xây dựng myObject từ nó. Trong C++ 03 11 và 14, việc xây dựng bản sao/di chuyển này được ưu tiên. Trong C++ 17, giá trị "hướng dẫn xây dựng" được áp dụng trực tiếp cho myObject. Trong thực tế, kết quả này trong cùng một mã máy (trừ khi bạn là một kẻ ngốc và trình bày rõ ràng trình biên dịch của bạn để không elide xây dựng).

Tóm lại, nó hoạt động. Nhược điểm duy nhất là việc phân bổ đôi khối điều khiển riêng biệt từ phân bổ Object.

+0

Đó là một câu trả lời tuyệt vời, cảm ơn bạn :) – nikaza

+0

Tôi gặp lỗi ... Cách thức là hàm 'token()' là riêng tư ... vì vậy nó không thể được sử dụng trong cuộc gọi 'make_shared <>()'. –

+2

@alexis vấn đề là việc chia sẻ chỉ có thể được gọi với mã thông báo trong ngữ cảnh bạn có quyền truy cập vào dữ liệu cá nhân từ lớp (hoặc nơi bạn được cấp phép bằng cách gửi cho bạn mã thông báo từ ngữ cảnh đó).Đơn giản chỉ cần làm cho constructor công khai nếu bạn không muốn kiểm soát truy cập vào nó ở tất cả. Tức là 'static std :: shared_ptr Class :: make() {return std :: make_shared (mã()); } ' – Yakk

Các vấn đề liên quan