C++ smart pointer const correctness

后端 未结 5 1186
你的背包
你的背包 2020-12-24 10:56

I have a few containers in a class, for example, vector or map which contain shared_ptr\'s to objects living on the heap.

For example

template 

        
5条回答
  •  春和景丽
    2020-12-24 11:51

    Prologue

    The const qualifier changes the behaviour of std::shared_ptr, just like it affects the legacy C pointers.

    Smart pointers should be managed and stored using the right qualifiers at all times to prevent, enforce and help programmers to treat them rightfully.

    Answers

    1. When someone passes a shared_ptr into the class, do I store it as a shared_ptr or shared_ptr inside the vector and map or do I change the map, vector types?

    If your API accepts a shared_ptr, the unspoken contract between the caller and yourself is that you are NOT allowed to change the T object pointed by the pointer, thus, you have to keep it as such in your internal containers, e.g. std::vector>.

    Moreover, your module should NEVER be able/allowed to return std::shared_ptr, even though one can programatically achieve this (See my answer to the second question to see how).

    1. Is it better to instantiate classes as follows: MyExample? That seems unduly restrictive, because I can never return a shared_ptr?

    It depends:

    • If you designed your module so that objects passed to it should not change again in the future, use const T as the underlying type.

    • If you your module should be able to return non-const T pointers, you should use T as your underlying type and probably have two different getters, one that returns mutable objects (std::shared_ptr) and another that returns non-mutable objects (std::shared_ptr).

    And, even though I hope we just agreed you should not return std::shared_ptr if you have a const T or std::shared_ptr, you can:

    const T a = 10;
    auto a_ptr = std::make_shared(const_cast(a));
    
    auto b_const_ptr = std::make_shared();
    auto b_ptr = std::const_pointer_cast(b_const_ptr);
    

    Full blown example

    Consider the following example that covers all the possible permutations of const with std::shared_ptr:

    struct Obj
    {
      int val = 0;
    };
    
    int main()
    {
        // Type #1:
        // ------------
        // Create non-const pointer to non-const object
        std::shared_ptr ptr1 = std::make_shared();
        // We can change the underlying object inside the pointer
        ptr1->val = 1;
        // We can change the pointer object
        ptr1 = nullptr;
    
        // Type #2:
        // ------------
        // Create non-const pointer to const object
        std::shared_ptr ptr2 = std::make_shared();
        // We cannot change the underlying object inside the pointer
        ptr2->val = 3; // <-- ERROR
        // We can change the pointer object
        ptr2 = nullptr;
    
        // Type #3:
        // ------------
        // Create const pointer to non-const object
        const std::shared_ptr ptr3 = std::make_shared();
        // We can change the underlying object inside the pointer
        ptr3->val = 3;
        // We can change the pointer object
        ptr3 = nullptr; // <-- ERROR
    
        // Type #4:
        // ------------
        // Create const pointer to non-const object
        const std::shared_ptr ptr4 = std::make_shared();
        // We can change the underlying object inside the pointer
        ptr4->val = 4; // <-- ERROR
        // We can change the pointer object
        ptr4 = nullptr; // <-- ERROR
    
        // Assignments:
        // ------------
        // Conversions between objects
        // We cannot assign to ptr3 and ptr4, because they are const
        ptr1 = ptr4 // <-- ERROR, cannot convert 'const Obj' to 'Obj'
        ptr1 = ptr3;
        ptr1 = ptr2 // <-- ERROR, cannot convert 'const Obj' to 'Obj'
    
        ptr2 = ptr4;
        ptr2 = ptr3;
        ptr2 = ptr1;
    }
    

    Note: The following is true when managing all types of smart pointers. The assignment of pointers might differ (e.g. when handling unique_ptr), but the concept it the same.

提交回复
热议问题