2016-03-21 18 views
8

Đó là cách chính xác để kéo dài tuổi const đúng đắn của một lớp cho các thành viên nhọn của nó? Trong đoạn mã ví dụ, là phiên bản ổn định của phương pháp get sẽ tạo ra một std::shared_ptr có tài liệu tham khảo truy cập cũng giống như các thành viên nội bộ m_b, hoặc là nó bắt đầu một lần nữa kể từ 0?gợi ý chung và đúng đắn const

class A 
{ 
    std::shared_ptr<B> m_b; 

public: 

    std::shared_ptr< const B > get_b() const 
    { 
     return m_b; 
    } 

    std::shared_ptr<B> get_b() 
    { 
     return m_b; 
    } 
} 
+0

Bạn có thể muốn cũng thực hiện 'get_const_b() ', tương tự như phương pháp' cbegin()' và 'cend()' của các thùng chứa tiêu chuẩn (http://en.cppreference.com/w/cpp/container/vector/begin). – filipos

Trả lời

7

shared_ptr sẽ luôn duy trì số lượng tham chiếu khi bạn tạo từ số khác shared_ptr; cách duy nhất để sử dụng nó không an toàn là xây dựng từ một con trỏ liệu: shared_ptr<...>(my_ptr.get()) // don't do this.

Trình bao bọc propagate_const, nằm trong Thư viện cơ bản TS v2, vì vậy có thể sẽ sớm có trong triển khai của bạn.

0

Câu trả lời có thể được suy luận bằng cách thực hiện một số thử nghiệm với use_count().

Cũng cần chú ý cách giải quyết phương pháp có thể không hoàn toàn rõ ràng:

class B {}; 

class A { 
    std::shared_ptr<B> m_b; 

public: 
    A() { m_b = std::make_shared<B>(); } 

    std::shared_ptr<const B> get_b() const { 
    std::cout << "const" << std::endl; 
    return m_b; 
    } 

    std::shared_ptr<B> get_b() { 
    std::cout << "non const" << std::endl; 
    return m_b; 
    } 
}; 

int main(int, char **) { 

    A a; 

    std::shared_ptr<B> b = a.get_b(); 

    std::cout << b.use_count() << std::endl; 

    std::shared_ptr<const B> cb = a.get_b(); 

    std::cout << cb.use_count() << std::endl; 

    const A &a_const_ref = a; 

    std::shared_ptr<const B> ccb = a_const_ref.get_b(); 

    std::cout << ccb.use_count() << std::endl; 

    return 0; 
} 

Output:

non const 
2 
non const 
3 
const 
4 
+0

Xin vui lòng, bạn có thể làm rõ những gì chính xác là phản trực giác ở đây, và những loại pitfall nào bạn mong đợi? Kết quả có vẻ khá hợp lý và an toàn đối với tôi. – filipos

+0

Người ta có thể nghĩ rằng lệnh gọi thứ hai để 'get_b()' giải quyết thành phiên bản 'const'. Ngoài ra, cùng một bộ đếm ref được tăng lên bởi cuộc gọi thứ ba, đó là câu trả lời cho chính câu hỏi đó. –

+0

Tôi lặp lại câu trả lời của mình một chút, không có ý định nhấn mạnh quá nhiều vào những cạm bẫy. –