在指针向量上排序更改向量副本中的数据?

Ela*_*782 0 c++ boost stl shared-ptr c++11

我有一个指向对象的指针向量,并且在某些时候,使用该向量的子元素创建第二个向量.现在,对原始向量进行排序会更改第二个向量中的元素(排序后其中的元素完全不同).

这是预期的行为吗?它与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'
Run Code Online (Sandbox Code Playgroud)

Ben*_*igt 6

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

您可以改为使用普通迭代器并在比较步骤中执行取消引用.Lambdas让这更容易:

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

带有可重用仿函数的版本(感谢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());
Run Code Online (Sandbox Code Playgroud)

C++ 14增加了多态lambda,它可以让你编写一个[](a, b)(*a > *b)像第二个(仿函数)解决方案一样的短lambda .无需命名迭代器类型(例如with decltype).

  • @ Ela782:这是因为`std :: sort`对元素进行了两次操作 - 比较和交换,当你使用间接迭代器时,它们会影响*both*.但是你真的想要处理比较的值,但是用于交换目的的指针. (2认同)