[英]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
对于前
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给定一个名为
MyObject
的 class (或结构)使用
std:queue<std::unique_ptr<MyObject>>queue;
rather than而不是
std:queue<MyObject> queue;
(it can be any container, not necessarily a queue) (可以是任何容器,不一定是队列)
Why should someone use option 1 rather than 2?为什么有人应该使用选项 1 而不是 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>
.因此,如果您想将派生对象保存在容器中,则不能拥有
std::queue<MyObject>
。 One options is unique_ptr
, another is reference_wrapper
一个选项是
unique_ptr
,另一个是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.例如
std::vector::insert
或容器本身的移动。 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).在这种情况下,
std::unique_ptr<MyObject>
确保引用是有效的,不管容器对它做了什么(ofc,只要unique_ptr
是活动的)。
In the following example in Objects
you can add a bunch of objects in a queue.在下面的
Objects
示例中,您可以在队列中添加一堆对象。 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. (*) 我在这里使用“参考”的英文含义,而不是 C++ 类型。 Any way to refer to an object (eg via a raw pointer)
引用 object 的任何方式(例如通过原始指针)
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.用例:您希望将某些内容存储在具有常量索引的
std::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.如果你使用指针,你可以删除一个指向 object 并设置
vector[i] = nullptr
,(并且稍后检查它)这是你在存储对象本身时不能做的事情。 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.如果您要存储对象,则必须将实例保留在向量中并使用标志
bool valid
或其他东西,因为如果您要从向量中删除 object,则该对象的索引更改为 -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.注意:如对此答案的评论中所述,如果您有权访问 C++17 或更高版本,则可以使用
std::optional
进行归档。
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:以下是在对象上使用指针的一些好处:
Also, polymorphism is considered as one of the important features of Object-Oriented Programming.此外,多态性被认为是面向对象编程的重要特征之一。 In C++ polymorphism is mainly divided into two types:
C++中的多态性主要分为两种:
This type of polymorphism is achieved by function overloading or operator overloading.这种类型的多态性是通过 function 重载或运算符重载来实现的。
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.这种类型的多态性是通过 Function 覆盖实现的,如果我们想使用基础 class 来使用这些函数,则必须使用指针而不是对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.