How do I get the value of this void* back?

Viewed 362

I have a void pointer of which I can set the value just fine (at least I think I did it right). But when I try to get the value of what is stored there, all I get nothing back. Doesn't matter if the void* points to a string or int or anything else. What am I missing here?

class Vertex2{
public:
    int _id;

    void *_data;

    template<typename T>
    T getData() {
        T *value = (T*)_data;
        return *value;
    }

    template <typename T>
    void setData(T data) {
        _data  = &data;
    }
};
4 Answers

void setData(T data) receives data by value.

Setting a pointer to data therefore is only valid for the lifetime of that function call.

After that, the pointer dangles, and dereference behaviour is undefined.

template <typename T>
void setData(T data) {
    _data  = &data;
}

let's check what's going on here. You store a pointer to a local variable (method argument actually). Right after you leave the method the local var is destroyed and its memory is free to be reused. Now your void* points to the same memory address but the memory can contain anything.

Try it like this:

// the entire class should be templated and you should not cast the data to void
template<typename T>
class Vertex2
{
public:
    int _id;
    // data is no longer void
    T m_data;

    // now returning a const pointer to your data and protect it against manipulation from outside
     getData() const {
        return m_data;
    }

    // was setting the address of a temporary, that will not work. Now it takes a copy and moves that to the member.
    void setData(T data) {
        m_data = std::move(data);
    }
};

I have added comments in the code.

As to your code

template <typename T>
void setData(T data) {
    _data  = &data;
}

Do not do that. You store the address to the temporary copy of data. This will go wrong!

void *_data;

Do not store the data as void, template the class like this:

template<typename T>
class Vertex2
{
    T m_data;
    .
    .
    .

There's nothing stored there.

You set the pointer to point to a function argument, that then went out of scope.

You can cast as much as you like, but that object has gone!

This design won't work unless you dynamically allocate.

Consider a std::variant or something instead.

Related