簡體   English   中英

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

[英]std::reverse on boost::ptr_vector slices objects?

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

boost::ptr_vector上的std::reverse()調用std::iter_swap() ,后者又調用std::swap ,后者通過創建臨時副本來交換項目。

但是,臨時副本確實會切片“派生”對象。 如您所見, Derived對象1和4的int g 交換,因此對象在交換后被破壞。

這種行為使我感到困惑。 boost::ptr_vector不是容器來避免這種問題嗎?

我需要的是一個虛擬副本構造函數 ,在C ++中不存在。

我該如何解決? 我是否需要為Base實現一個虛擬交換函數,以便虛擬調度調用Derived另一個交換成員函數?

編輯:為什么要首先復制對象? 由於向量僅存儲指針,因此將其反轉應該是指針的交換,而不是指向的對象! 有功能嗎?

Boost的ptr_vector類包含成員函數,這些成員函數的工作是操縱基礎指針。 但是公共接口在很大程度上隱藏了向量在內部存儲指針的事實。 想法是產生某種行為,就像它直接包含對象一樣,但是在內部存儲指針以避免將對象放入容器時切片。 但是,如果將對象從容器中復制到基本類型的對象中,則它將切片。 因此,您不得在ptr_vector上調用此類函數。

不幸的是,這意味着在將任何算法應用於ptr_vector ,您需要確切了解它的作用。

一種可能的解決方法是使用

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

代替。 它反轉指針而不是自間接迭代器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM