是否可以在C ++中的类和向量中都存储一个unique_ptr?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否可以在C ++中的类和向量中都存储一个unique_ptr?相关的知识,希望对你有一定的参考价值。

我试图持有指向向量(来自Base类)和Derivated类对象的唯一指针,因此以后我可以为所有人调用一个方法。但是我想从Derivated类中调用aswell方法,因此我也需要存储它们的引用。

class Foo
{
     vector<unique_ptr<Base>> bar;
     unique_ptr<Derivated1> bar2;
     unique_ptr<Derivated2> bar3;
}

Foo::Foo(){
     this->bar2 = make_unique<Derivated1>();
     this->bar2->doSomethingDerivated1();
     this->bar3 = make_unique<Derivated2>();
     this->bar->push_back(move(bar2));
     this->bar->push_back(move(bar3));
}

Foo::callForAll() {
     for (const auto& foo: this->bar) foo->doSomethingBase();
}

Foo::callForDerivated1() {
     this->bar2->doSomethingDerivated1();
}

是否有可能这样?以我的理解,此代码很可能会失败。将bar2bar3位置移至nullptr吗?创建一个unique_ptr,用bar2->get()存储原始指针,然后将push_backvector起作用吗?

注意:这些对象仅属于此类,因此唯一是有意义的。

答案

没有unique_ptr的要点是唯一的。这意味着您无法复制它。

但是,您可以复制unique_ptr管理的基础指针的副本。例如:

unique_ptr<Foo> foo(new Foo);
Foo* foo_copy = foo.get();

执行此操作时需要注意以下几点:

  1. 不删除foo_copy。那就是unique_ptr的工作。如果删除foo_copy,则将犯双重删除的罪恶,这种行为具有不确定的行为(即,允许编译器生成发射核导弹的代码)。

  2. 销毁foo_copy之后请勿使用foo,因为销毁foo时,将删除基础指针(除非foo放弃了对基础指针的所有权,并且尚未删除基础指针通过其他方式)。这是免费使用后的罪过,并且也有UB。

移动是unique_ptr放弃所有权的一种方法。一旦移出unique_ptr,它便不再指向任何东西(这就是移动的全部要点;当您从A步行到B时,您不再位于A,因为只有一个人,您已经决定了而是位于B)。我相信,尝试在空的unique_ptr上使用->运算符调用方法也是UB。

似乎您应该做的是

  1. vector<unique_ptr<Base>> v;
  2. Derived* ob = v[i].get();

让我重申这有点危险和不寻常。

Tangent:我非常怀疑您没有使用虚拟方法; virtual实际上应该是默认值(有点像默认值是double,而不是float,即使float看起来像是并且应该是默认值)。实际上,我发现您在使用继承。继承是有史以来最被高估的功能之一。我怀疑这可能是您的麻烦所在。例如,Go语言甚至没有继承,但确实具有多态性(即同一接口的不同实现)。

PS:请不要通过调用UB意外消灭人类。

以上是关于是否可以在C ++中的类和向量中都存储一个unique_ptr?的主要内容,如果未能解决你的问题,请参考以下文章

将对象转换为存储在变量中的类

char能储存啥?

是否可以将结果存储在 vDSP 框架中的输入向量之一中

c ++在析构函数中删除向量类成员内存

C语言中都有哪些存储类型?

如何找到存储在 C++ 向量中的对象的类方法?