在boost :: ptr_vector切片对象上的std :: reverse?

时间:2014-07-19 15:35:53

标签: c++ std swap boost-ptr-container

BaseDerived成为包含数据成员的类:

class Base {
public:
    Base(int i):f(i)     { }
    virtual void print() { cout << "base " << f << endl; }
    int f;
};

class Derived: public Base {
public:
    Derived(int i):Base(0),g(i) {  }
    void print() { cout << "derived " << g << endl; }
    int g;
};

现在在堆上创建BaseDerived的一些实例,并将它们存储在boost::ptr_vector中:

int main(int argc, char *argv[])
{
    boost::ptr_vector<Base> v;
    v.push_back(new Derived(1));
    v.push_back(new Base(2));
    v.push_back(new Base(3));
    v.push_back(new Derived(4));

打印所有对象:

    for (std::size_t i(0); i != v.size(); ++i)
        v[i].print();

然后反转并重新打印:

    std::reverse(v.begin(), v.end());
    for (std::size_t i(0); i != v.size(); ++i)
        v[i].print();
}

此程序打印:

derived 1
base 2
base 3
derived 4
derived 1
base 3
base 2
derived 4
std::reverse() boost::ptr_vector上的{p> std::iter_swap()调用std::swap,后者调用int g,通过创建临时副本来交换项目。

但是,临时副本会对Derived对象进行切片。如您所见,Derived对象1和4的boost::ptr_vector 交换,因此交换后对象将被破坏。

这种行为让我很困惑。不是Base容器,以避免这种问题吗?

我需要的是虚拟副本构造函数,它在C ++中不存在。

我该如何解决这个问题?我是否需要为Derived实现虚拟交换功能,以便虚拟调度调用{{1}}的另一个交换成员函数?

编辑:为什么要首先复制对象?因为向量只存储指针,所以反转它应该是指针的交换,而不是指向的对象! 有没有这样做的功能?

2 个答案:

答案 0 :(得分:1)

Boost的ptr_vector类包含成员函数,其作用是操作底层指针。但是公共接口在很大程度上隐藏了向量内部存储指针的事实。我们的想法是生成一些行为,就好像它直接包含对象,但内部存储指针以避免在将对象放入容器时切片。但是如果将一个对象从容器中复制到基类型的对象中,那么它将进行切片。所以你不能在ptr_vector s上调用这些函数。

不幸的是,这意味着在将任何算法应用于ptr_vector之前,您需要准确理解它的作用。

答案 1 :(得分:0)

一种可能的解决方法是使用

std::reverse(v.base().begin(), v.base().end());

代替。它反转指针而不是自我间接迭代器。