Domanda

The following actually compiles and runs;

template <typename T> 
class heap_ptr
{
public:
    heap_ptr(T* p) : t(p) {}
    heap_ptr(const heap_ptr&) = delete;
    template<typename ... U> heap_ptr( U ... u )
    {
        t = new T(u...);
    }
    T* operator -> () { return t; }
    // T& operator = (const T& o) { (*t)=o; return *t; }
    operator T () { return *t; }
    ~heap_ptr() { delete t; }
private:
    T* t;
};

struct A { int x,y; A(int x,int y):x(x),y(y){} };

void try_it()
{
    heap_ptr<A> woop {8,11};
    A a{5,3};
    woop = a; // <- here
}

However, the marked assignment puts garbage in woop. Why does it compile, and why do I get garbage in woop?

note: if I uncomment the assignment operator it works as expected, that's not the issue.

È stato utile?

Soluzione

if I uncomment the assignment operator it works as expected, that's not the issue

That's exactly the issue. Copy-assignment operator generated by default will copy the pointer, not the object behind it. And then the temporary object heap_ptr(a) is destroyed, deleting the data pointed to.

Altri suggerimenti

The problem is caused by the fact that by not implementing your operator= you are relying on the default one which will copy the pointer of the temporary object and then destroy it, leaving you with an invalid pointer once the copy is finished.

This is an instance of the set of problems that derive by not following the rule of three (five in C++11). When you can, you should follow the rule of zero, though.


You are trying to reimplement a smart pointer. Just use std::unique_ptr and it won't compile, like you expect:

struct A { int x,y; A(int x,int y):x(x),y(y){} };

void try_it()
{
    std::unique_ptr<A> woop{ new A(8, 11) };
    A a{5,3};
    woop = a;
}

Live demo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top