对指针向量进行排序会更改该向量副本中的数据

sort on a vector of pointers changes data in a copy of the vector?

本文关键字:向量 副本 数据 指针 排序      更新时间:2023-10-16

我有一个指向对象的指针向量,并且在某个时候,创建了第二个包含该向量的子元素的向量。现在,对原向量进行排序会改变第二个向量中的元素(排序后,第二个向量中的元素完全不同)。

这是预期的行为吗?它和make_indirect_iterator有关系吗?是否有更好的解决方案(假设我想保持一个指针向量)?

std::vector<std::shared_ptr<MyObj>> vecAll;
std::vector<std::shared_ptr<MyObj>> vecSub;
// fill vecAll with something...
for(auto obj : vecAll) {
    if( obj->x >=0 ) {
        vecSub.push_back(obj);
    }
}
// 3 objects in 'vecSub'
std::sort(boost::make_indirect_iterator(vecAll.begin()), boost::make_indirect_iterator(vecAll.end()), std::greater<MyObj>());
// now there are 3 DIFFERENT objects in 'vecSub'

是的,它与make_indirect_iterator有关。这将导致对象值被交换,而不仅仅是指针的重新排序。

可以使用普通迭代器,并在比较步骤中执行解引用操作。lambda使这更容易:

typedef decltype(vecAll.front()) iter;
std::sort(vecAll.begin(),
          vecAll.end(),
          [](iter a, iter b) { return *a > *b; });

带有可重用函子的版本(感谢MooingDuck的建议):

struct indirect_greater
{
    template<typename iter>
    bool operator()(iter a, iter b) const { return *a > *b; }
};
std::sort(vecAll.begin(), vecAll.end(), indirect_greater());

c++ 14增加了多态lambda,这将允许您编写一个短lambda [](a, b)(*a > *b),其行为类似于第二个(函子)解决方案。不需要命名迭代器类型(例如用decltype)