set_interaction 自定义矢量无效的示例

set_interaction example with custom vector not working

我正在寻找两个自定义向量的交集 - v and w -,然后从原始向量 - v 中删除公共元素。但是在我的例子中 y 的大小总是 0

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class A{
    public:
    int x;
    A(int i) { x = i; } 
    ~A() {}
    void getx() { cout << x << " "; } 
    friend ostream &operator<<(ostream &o, const A&a) {
        cout << a.x;
        return o;
    }
};

struct mycomparer {
    bool operator()(const A* a, const A* b) {
        return a->x < b->x;
    }
};

int main()
{
    vector<A*> v;
    v.push_back(new A(1));
    v.push_back(new A(2));
    v.push_back(new A(4));
    v.push_back(new A(3));
    v.push_back(new A(5));

    vector<A*> w;
    w.push_back(new A(3));
    w.push_back(new A(2));

    vector<A*> y;
    vector<A*>::iterator it, st;
    it = set_intersection(v.begin(), v.end(), w.begin(), w.end(), y.begin(), mycomparer());

    cout << " y size "  << y.size() << endl;

    if (y.size()) {
        for (st = y.begin(); st != y.end(); st++)
            v.erase(st);
    }

    for (st = v.begin(); st != v.end(); st++) {
        printf("%d ", (*st)->x);
    }
    cout << endl;

    return 0;
}

这只是我编写的示例,我不打算检查任何其他 C++ 规则。

1) 在向量 w 中,您应该先按 new A(2),然后 new A(3)。对于您的实际代码,您的向量必须事先根据比较器排序,如前文评论所述,否则您绝对不能使用 set_intersection.

2) 向量 y 的大小为 0,因为 set_intersection 不会 在迭代器中插入 新元素,而是 分配 与运算符 =。您应该使用 std::back_inserter(y) 而不是 y.begin(),这实际上会在赋值时插入元素。

您没有遵守 std::set_intersection 的要求。

Constructs a sorted range beginning at d_first consisting of elements that are found in both sorted ranges [first1, last1) and [first2, last2). If some element is found m times in [first1, last1) and n times in [first2, last2), the first std::min(m, n) elements will be copied from the first range to the destination range. The order of equivalent elements is preserved. The resulting range cannot overlap with either of the input ranges.

vw 都未排序 w.r.t mycomparer。这是第一个未定义的行为。

仅仅通过 y.begin() 并不意味着元素被添加到 y,因为你需要 std::back_inserter(y)。这是第二个未定义的行为。

您没有遵守std::vector::erase的要求。它的参数是 that vector 的迭代器。您正在使用来自 y 的迭代器,而不是 v。这是第三个未定义的行为。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

class A{
    public:
    int x;
    A(int i) { x = i; } 
    ~A() {}
    void getx() { cout << x << " "; } 
    friend ostream &operator<<(ostream &o, const A&a) {
        cout << a.x;
        return o;
    }
};

struct mycomparer {
    bool operator()(const A* a, const A* b) {
        return a->x < b->x;
    }
};

int main()
{
    std::vector<A*> v;
    v.push_back(new A(1));
    v.push_back(new A(2));
    v.push_back(new A(4));
    v.push_back(new A(3));
    v.push_back(new A(5));

    std::sort(v.begin(), v.end(), mycomparer());

    std::vector<A*> w;
    w.push_back(new A(3));
    w.push_back(new A(2));

    std::sort(w.begin(), w.end(), mycomparer());

    std::vector<A*> y;
    set_intersection(v.begin(), v.end(), w.begin(), w.end(), std::back_inserter(y), mycomparer());

    std::cout << " y size "  << y.size() << std::endl;

    for (st = y.begin(); st != y.end(); st++)
        v.erase(std::find(v.begin(), v.end(), *st));

    for (st = v.begin(); st != v.end(); st++) {
        std::cout << (*st)->x) << std::endl;
    }

    return 0;
}

顺便说一句,您可以使用 std::set_difference 来查找 v 中的元素,而不是直接在 w 中查找元素。

你的代码有很多问题...我只是把它们放在修改后的代码中

#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>

// don't using namespace std;

class A {
private:
    int x; // don't expose internals
public:
    constexpr A(int i) noexcept : x(i) {}

    constexpr int GetX() const noexcept { return x; } // don't make a getter to print

    friend std::ostream& operator<< (std::ostream& o, const A& a) {
        o << a.x; // don't push to cout in an ostream operator <<
        return o;
    }
};

// use lambda instead of functors
static constexpr auto mycomparer =
[](std::shared_ptr<A> const& a, std::shared_ptr<A> const& b) noexcept {
        return a->GetX() < b->GetX();
};

int main()
{
    // you were not deleting the new elements: memory leak
    std::vector<std::shared_ptr<A>> v; // e.g. use smart pointers
    v.push_back(std::make_shared<A>(1));
    v.push_back(std::make_shared<A>(2));
    v.push_back(std::make_shared<A>(4));
    v.push_back(std::make_shared<A>(3));
    v.push_back(std::make_shared<A>(5));

    std::vector<std::shared_ptr<A>> w;
    w.push_back(std::make_shared<A>(3));
    w.push_back(std::make_shared<A>(2));

    std::vector<std::shared_ptr<A>> y;

    //you have to sort before calling set_intersection
    std::sort(std::begin(v), std::end(v), mycomparer);
    std::sort(std::begin(w), std::end(w), mycomparer);

    std::set_intersection(
        std::cbegin(v), std::cend(v), // use const iterators
        std::cbegin(w), std::cend(w),
        std::back_inserter(y), mycomparer); // you cannot iterate over an empty array. Use the backinserter

    std::cout << " y size " << y.size() << '\n';

    // you cannot use an iterator to a vector y to delete from vector v!
    //if (y.size() > 0) { // not required
        for (auto const& el : y)
            v.erase(std::find(std::cbegin(v), std::cend(v), el)); 
    //}

    for (auto const& el : v) {
        std::cout << el->GetX() << " ";
    }
    std::cout << '\n'; // prefer \n over endl for speed

    //return 0; // not required
}