1

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

Jim
  • 33
  • 3
  • If you look at the docs for [`std::unique_ptr`](http://en.cppreference.com/w/cpp/memory/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 Jun 10 '19 at 17:26
  • 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 it – Jim Jun 10 '19 at 17:50
  • 1
    The premise seems to be that `myVec[0]` makes a copy. It does not. – Lightness Races in Orbit Jun 10 '19 at 17:50
  • @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 Jun 10 '19 at 18:05

2 Answers2

3

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( ) };

WBuck
  • 2,918
  • 2
  • 17
  • 22
  • Wont it boil down to the same problem using the [] operator? I will get an "...error: use of deleted function 'std::unique_ptr<_tp _dp="">::unique_pt..." cause it tries to use a copy constructor? – Jim Jun 10 '19 at 17:47
  • I don't see anything here requiring a copy constructor. `[]` does not make a copy. If you get that error now then you did not properly copy WBuck's suggested code. – Lightness Races in Orbit Jun 10 '19 at 17:49
  • I must have made some misstake, the suggestions here work fine. Thanks for the help guys – Jim Jun 10 '19 at 18:07
0

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];
OdedR
  • 123
  • 7