2

I have a vector that holds Objects that are derived classes from a Base class "SceneObject". For this task, I found that I had to use unique pointers, as seen here:

vector<std::unique_ptr<SceneObject>> objects;

To put my objects inside this vector, I allocate memory on the heap with the new keyword:

objects.emplace_back(new Sphere(glm::vec3(0.9, -1.925, -6.69), 0.825, sphereMaterial));

I access functions from these objects in a loop like:

objects[k]->intersect(...);

But my problem is that I want to initialize a variable "SceneObject" that will contain one of the objects stored in this vector to perform some checks later... I'm trying to store the pointer instead, as I think I should be doing, but I'm getting a compiler error when doing this:

SceneObject* object = NULL;
for(...)
    object = &objects[k];

The error:

boilerplate.cpp: In function 'int main(int, char**)':
boilerplate.cpp:606:15: error: cannot convert '__gnu_cxx::__alloc_traits<std::allocator<std::unique_ptr<SceneObject> > >::value_type* {aka std::unique_ptr<SceneObject>*}' to 'SceneObject*' in assignment
    object = &objects[k];
           ^

I used this method as seen in this example code for creating my base/derived classes.

Any suggestion as to how I should initialize this variable with my object?

jjcastil
  • 189
  • 1
  • 15

2 Answers2

3

You need to call get on std::unique_ptr to "unwrap" the raw pointer stored inside:

SceneObject* object = NULL;
for(...)
    object = objects[k].get();

Note that you can avoid unwrapping the pointer in situations when you own the API: std::unique_ptr provides dereference operators, allowing you to treat them as if they were actual pointers.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

Remember what a unique_ptr actually is: it is an object which manages your pointer and only allows one instance to point to a given object.

So an element of your vector is a unique_ptr which means that when you do objects[k] you are getting a unique_ptr object back. You are trying to initialize a SceneObject* pointer to a unique_ptr* here:

SceneObject* object = NULL; object = &objects[k];

But obviously SceneObject* != unique_ptr*

The goal of smart pointers is to avoid using raw pointers, so if you're using unique_ptr's in the vector, and are fine with the vector element being destructed, you should use unique_ptr<SceneObject> object; with your loop too. Then it's just:

for(...) object = objects[k];

If you want them to remain valid in the vector, you should be using shared_ptr's in both locations.

Brandon
  • 53
  • 6