简体   繁体   中英

Reason for using smart pointers with a container

Simply written I would like to ask "what is a good reason to use smart pointers?" for ex std::unique_ptr

However, I am not asking for reasons to use smart pointers over regular (dumb) pointers . I think every body knows that or a quick search can find the reason.

What I am asking is a comparison of these two cases:

Given a class (or a struct) named MyObject use

  1. std:queue<std::unique_ptr<MyObject>>queue;

rather than

  1. std:queue<MyObject> queue;

(it can be any container, not necessarily a queue)

Why should someone use option 1 rather than 2?

That is actually a good question.

There are a few reasons I can think of:

  • Polymorphism works only with references and pointers, not with value types. So if you want to hold derived objects in a container you can't have std::queue<MyObject> . One options is unique_ptr , another is reference_wrapper

  • the contained objects are referenced (*) from outside of the container. Depending on the container, the elements it holds can move , invalidating previous references to it. For instance std::vector::insert or the move of the container itself. In this case std::unique_ptr<MyObject> assures that the reference is valid, regardless of what the container does with it (ofc, as long as the unique_ptr is alive).
    In the following example in Objects you can add a bunch of objects in a queue. However two of those objects can be special and you can access those two at any time.

     struct MyObject { MyObject(int); }; struct Objects { std::queue<std::unique_ptr<MyObject>> all_objects_; MyObject* special_object_ = nullptr; MyObject* secondary_special_object_ = nullptr; void AddObject(int i) { all_objects_.emplace(std::make_unique<MyObject>(i)); } void AddSpecialObject(int i) { auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i)); special_object_ = emplaced.get(); } void AddSecondarySpecialObject(int i) { auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i)); secondary_special_object_ = emplaced.get(); } };

(*) I use "reference" here with its english meaning, not the C++ type. Any way to refer to an object (eg via a raw pointer)

Usecase: You want to store something in a std::vector with constant indices, while at the same time being able to remove objects from that vector.

If you use pointers, you can delete a pointed to object and set vector[i] = nullptr , (and also check for it later) which is something you cannot do when storing objects themselves. If you'd store Objects you would have to keep the instance in the vector and use a flag bool valid or something, because if you'd delete an object from a vector all indices after that object's index change by -1.


Note: As mentioned in a comment to this answer, the same can be archieved using std::optional , if you have access to C++17 or later.

The first declaration generates a container with pointer elements and the second one generates pure objects.

Here are some benefits of using pointers over objects:

  1. They allow you to create dynamically sized data structures.
  2. They allow you to manipulate memory directly (such as when packing or unpacking data from hardware devices.)
  3. They allow object references(function or data objects)
  4. They allow you to manipulate an object(through an API) without needing to know the details of the object(other than the API.)
  5. (raw) pointers are usually well matched to CPU registers, which makes dereferencing a value via a pointer efficient. (C++ “smart” pointers are more complicated data objects.)

Also, polymorphism is considered as one of the important features of Object-Oriented Programming. In C++ polymorphism is mainly divided into two types:

  • Compile-time Polymorphism

This type of polymorphism is achieved by function overloading or operator overloading.

  • Runtime Polymorphism

This type of polymorphism is achieved by Function Overriding which if we want to use the base class to use these functions, it is necessary to use pointers instead of objects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM