1
votes

I've created a std vector and pushed back a bunch of objects onto it using the std move, such as:

vector<unique_ptr<Foo> > myVec;
unique_ptr<Foo> a = make_unique<Foo>();
unique_ptr<Foo> b = make_unique<Foo>();
myVec.push_back(move(a));
myVec.push_back(move(b));

So far, so good.

Later on, I pass a reference of myVec to a function and try to access the data in the vector using the []-operators.

void someFunc(vector<unique_ptr<Foo> > &myVec)
{
    Foo* anObj = myVec[0];
}

After some reading, my guess is that this approach is not going to work, because the std vector will try and make a copy and unless I provide a copyconstructor on Foo that avoids actually making a copy it wont ever work. Am I correct? I think I saw some posts about using iterators, but I'd rather not if I dont have to.

EDIT1:

I did manage to work around it by the following (using iterator and then get to get the raw pointer)

void someFunc(vector<unique_ptr<Foo> > &myVec)
{
    int offset = 0; // Or some other offset into the vector
    auto it = myVec.begin() + offset;
    Foo* anObj = it.get();
    // ... Do something using anObj here...
}

I would think this is the way to go, as long as you dont foolishly try to retain the anObj and then free it manually somewhere. I could of course transfer ownership temporarly until Im done with it and then return the ownership but it feels like such a hassle. Any thoughts on the above approach?

Thanks in advance, /Jimmie

2
If you look at the docs for std::unique_ptr, you'll see if has a couple ways to return the pointer: namely release() and get() - read about them and decide which you want to do, or use the pointer directly from myVec[0] instead of copying it anywhere.Tony Delroy
Just posted an update EDIT, where I use the get() way. Am I understanding it correctly and is it an ok approach? I guess it was "mainly" designed to make unique_ptr work with legacy code where you have to do it. My code is new so I would hate to have an ugly pattern in it already. As far as I understand, my solution under the EDIT part is correct though. If not than I would be very happy to learn and correct itJim
The premise seems to be that myVec[0] makes a copy. It does not.Lightness Races in Orbit
@LightnessRacesinOrbit: You are correct. I must have made some other misstake, I've updated the code again and it seems to work just fine. Foo* anObj = myVec[0].get() works fine.Jim

2 Answers

3
votes

The anObj variable should be of type std::unique_ptr<Foo> and not a Foo*.

Code should be:

std::unique_ptr<Foo>& anObj{ myVec[ 0 ] };

Or

Foo* anObj{ myVec[ 0 ].get( ) };

0
votes

C++ not decide for you if using copy or reference assignment.

You should handle it by your self.

  • If you declare new variable and using = operator in the declaration line like int y = x; you are using copy constructor.
  • If you declare a variable with & before it, like int & y = x; you are taking the reference of x and store it in y.

In your example, you have 2 problems:

  1. You are trying to assign unique_ptr<Foo> to Foo* which is incorrect.
  2. You want to have the unique_ptr<Foo> reference so you should declare unique_ptr<Foo> reference like this: unique_ptr<Foo> & ref = myVec[0];