Search code examples
c++priority-queue

C++ Avoiding using copy constructor which is called by priorityqueue


I have this current setup:

#include <iostream>
#include <queue>
#include <vector>
class A
    {
        int val;
    public:
        A()
        {
            std::cout << "Inside A. Constructor with val =" << val << ".\n";
        }
        A(const A& msg)
        {
            std::cout << "Inside const A. Never want to come here. val =" << msg.val << ".\n";
        }
        bool operator()(const A* m1, const A* m2)
        {
            std::cout << "Inside () function.\n";
            std::cout << "m1: " << m1->GetVal() << " m2: " << m2->GetVal()<<"\n";
            return (m1->GetVal() < m2->GetVal());
        }
        void setVal(int input) { std::cout << "inside setVal.\n"; val = input; }
        int GetVal()const { return val; }

    };


    void specialPriorityQueue()
    {
        //init
        A* val = new A();
        val->setVal(5);
        std::priority_queue<A*, std::vector<A*>, A> pq;
        pq.push(val);

        A* val2 = new A();
        val2->setVal(3);
        pq.push(val2);

        delete val;
        delete val2;
    }
int main()
    {
        specialPriorityQueue();
return 0;
    }

outputs:

Inside A. Constructor with val =-85000000...
inside setVal.
Inside A. Constructor with val =-85000000...
Inside const A. Never want to come here. val =-85000000....
Inside A. Constructor with val =-85000000...
inside setVal.
Inside const A. Never want to come here. val =-85000000....
Inside () function.
m1: 5 m2: 3

My question is: Is there any way to avoid using the copy constructor by the priority queue. This causes undefined behaviour. I can't remove the function either as it has too much dependencies elsewhere.


Solution

  • That copy constructor is called when it creates the comparator object, which is also your element type, A.

    Use another type for comparator, e.g.:

    struct Compare
    {
        bool operator()(const A* m1, const A* m2) const {
            return m1->GetVal() < m2->GetVal();
        }
    };
    

    And then:

    std::priority_queue<A*, std::vector<A*>, Compare> pq;
    

    And, even better, use smart pointers to avoid memory leaks:

    struct Compare
    {
        bool operator()(std::unique_ptr<A> const& m1, std::unique_ptr<A> const& m2) const {
            return m1->GetVal() < m2->GetVal();
        }
    };
    
    void specialPriorityQueue() {
        std::unique_ptr<A> val(new A());
        val->setVal(5);
        std::priority_queue<std::unique_ptr<A>, std::vector<std::unique_ptr<A>>, Compare> pq;
        pq.push(move(val));
    
        std::unique_ptr<A> val2(new A());
        val2->setVal(3);
        pq.push(move(val2));
    }