[英]std::reverse on boost::ptr_vector slices objects?
令Base
和Derived
為具有數據成員的類:
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;
};
現在在堆上創建一些Base
和Derived
實例,並將它們存儲在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.