C++ stl容器,带有std::unique#ptr';s vs boost::ptr_容器

C++ stl容器,带有std::unique#ptr';s vs boost::ptr_容器,c++,stl,c++11,unique-ptr,boost-ptr-container,C++,Stl,C++11,Unique Ptr,Boost Ptr Container,有了c++11,我问自己c++11中是否有boost::ptr_容器的替代品。我知道我可以使用例如std::vector,但我不确定这是否是一个完整的替代品。处理这些情况的推荐方法是什么?它们确实解决了两个相似但不同的问题 指针容器是一种在容器中存储对象的方法,这些对象恰好是分配内存的指针,而不是值。他们竭尽全力掩盖自己是指针容器的事实。这意味着: 容器中的条目不能为空 从迭代器和函数获得的值是对类型的引用,而不是指向类型的指针 使用许多标准算法可能。。。棘手的我说的“狡猾”是指破碎。指针容器

有了c++11,我问自己c++11中是否有boost::ptr_容器的替代品。我知道我可以使用例如
std::vector
,但我不确定这是否是一个完整的替代品。处理这些情况的推荐方法是什么?

它们确实解决了两个相似但不同的问题

指针容器是一种在容器中存储对象的方法,这些对象恰好是分配内存的指针,而不是值。他们竭尽全力掩盖自己是指针容器的事实。这意味着:

  • 容器中的条目不能为空
  • 从迭代器和函数获得的值是对类型的引用,而不是指向类型的指针
  • 使用许多标准算法可能。。。棘手的我说的“狡猾”是指破碎。指针容器有自己的内置算法
但是,指针容器知道它们是指针的容器,因此它们可以提供一些新功能:

  • 一种
    clone
    成员函数,通过对对象类型使用某种“可克隆”概念来执行深度复制
  • 容器释放其对象所有权的能力(例如,在浅拷贝之后)
  • 用于将所有权转移到其他容器的内置函数
它们实际上是完全不同的概念。指针容器可以通过专门的函数自动完成许多手动操作


如果您确实需要一个指针容器,那么您可以使用
unique\u ptr
容器。但是,如果您需要存储一组碰巧由堆分配的对象,并且希望与它们玩涉及所有权等的特殊游戏,那么指针容器不是一个坏主意。

我决定编写一个简短的程序,将一些多态对象放入容器中(通过指针指向堆),然后将该容器与std::算法一起使用。我选择了
std::remove_if
作为示例

下面是如何使用
vector

我觉得很好。然而,我发现将其转换为ptr_向量有问题:

boost::ptr_vector<Animal> v;
v.push_back(new Cat);
v.push_back(new Sheep);
v.push_back(new Dog);
v.push_back(new Sheep);
v.push_back(new Cat);
v.push_back(new Dog);
for (auto const& p : v)
    p.speak();
std::cout << "Remove all sheep\n";
v.erase(
    std::remove_if(v.begin(), v.end(),
                   [](Animal& p)
                       {return dynamic_cast<Sheep*>(&p);}),
    v.end());
for (auto const& p : v)
    p.speak();

algorithm:1897:26: error: overload resolution selected deleted operator '='
                *__first = _VSTD::move(*__i);
                ~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~
test.cpp:75:9: note: in instantiation of function template specialization 'std::__1::remove_if<boost::void_ptr_iterator<std::__1::__wrap_iter<void
      **>, Animal>, Sheep *(^)(Animal &)>' requested here
        std::remove_if(v.begin(), v.end(),
        ^
test.cpp:12:13: note: candidate function has been explicitly deleted
    Animal& operator=(const Animal&) = delete;
            ^
1 error generated.
现在导致此错误输出:

Meow
Baa
Bark
Baa
Meow
Bark
Remove all sheep
destruct Cat
destruct Dog
Meow
Baa
Bark
Baa
destruct Cat
destruct Sheep
destruct Dog
destruct Sheep
使用
vector
时不会发生此运行时错误

存储指针容器但呈现引用容器的阻抗不匹配似乎与使用通用算法安全使用容器不一致。事实上,这就是为什么ptr_容器带有许多算法的自定义版本。使用ptr_容器执行此操作的正确方法是仅使用这些成员算法:

v.erase_if([](Animal& p)
                 {return dynamic_cast<Sheep*>(&p);});
v.erase\u如果([](动物和动物)
{return dynamic_cast(&p);});
如果您需要未作为ptr_容器成员提供的突变序列算法,请不要尝试使用
中的算法或其他第三方提供的通用算法

总之,boost::ptr_容器满足了真正的需求,而唯一的实用选项是
std::vector
。但是现在使用
std::vector
,开销参数消失了。而且C++11解决方案似乎具有安全性和灵活性两方面的优势。如果你需要“克隆语义学”,我会认真考虑编写自己的<代码> CalONYPPT/<代码>并使用STD容器和算法。

重复使用std::lib将使您的容器选项比boost lib更开放(例如无序的集合/映射、前进列表),并且它将使您的std::算法选项尽可能开放


这就是说,如果您已经使用boost::ptr_容器进行了工作、调试的代码,那么就没有迫切需要对其进行更改。

使用
unique_ptr
容器,您仍然必须取消对节点的引用,但除此之外,它们的行为应该基本相同。“开销参数消失了”-今天,我使用VS2013 Express进行了一些测试,令人惊讶的是,使用
ptr_vector
比使用
vector
(/O2 release build;boost 1.55)得到的性能结果始终更好。这篇评论附带了一个明确的YMMV,我还没有深入研究,但是如果一个人在一个非常有限的空间中,从性能角度来看,这两个方面都是很有趣的。很有趣,谢谢你的报道。我没有VS2013可供试验。是否
sizeof(unique_ptr)==sizeof(T*)
?/O2是最高的优化设置吗?是的,sizeof(uq_ptr)==sizeof(T*)==4/O2在VS中是“速度最大化”。我看到索引
[]
access.Hmm上的ptr_向量速度增加了50%。。我本以为在这两种情况下都会出现双重取消引用:相同的结果。我提出的唯一理论是
vector
案例没有完全内联。但这只是一个猜测。我把我的发现放在这里:我想你可以说其中一个是指针的容器,而另一个是用于多态对象的容器。。。
class Animal
{
public:
    Animal() = default;
    virtual ~Animal() = default;

    virtual void speak() const = 0;
};
Meow
Baa
Bark
Baa
Meow
Bark
Remove all sheep
destruct Cat
destruct Dog
Meow
Baa
Bark
Baa
destruct Cat
destruct Sheep
destruct Dog
destruct Sheep
v.erase_if([](Animal& p)
                 {return dynamic_cast<Sheep*>(&p);});