2

First I create a unique_ptr array of Foo objects. And then I move the objects to a vector as shown in the code below. But this code does not compile. Another question is since the objects were allocated using the array version of the new operator. What happens if an exception occurs and the program has to terminate early before I move back the objects to the unique_ptr array? In such a situation, the vector vec will destroy its contents using the delete operator, not the array version of the delete operator ? How do we solve this kind of problem?

class Foo
{
public:
  int id;

  Foo(){};
};

int main()
{
  int n = 10;

  std::unique_ptr<Foo []> fooarr(new Foo[n]);

  std::vector<std::unique_ptr<Foo>> vec;

  for( int i=0 ; i<n ; i++ ){
    fooarr[i].id = i;
  }

  for( int i=0 ; i<n ; i++ ){
    vec.push_back( std::move(fooarr[i]) );
  }

  //then move back the Foo objects from vec to fooarr

}

Here is what I got from the compiler.

main.cpp: In function 'int main()': main.cpp:47: error: no matching function for call to 'std::vector >, std::allocator > > >::push_back(Foo)' /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_vector.h:733: note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = std::unique_ptr >, _Alloc = std::allocator > >] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_vector.h:746: note: void std::vector<_Tp, _Alloc>::push_back(_Tp&&) [with _Tp = std::unique_ptr >, _Alloc = std::allocator > >]

3
  • @TartanLlama The first thing is that I don't understand the error. Do you? Commented Feb 2, 2016 at 12:02
  • @PeterA.Schneider It means that you can't push_back a Foo when a std::unique_ptr<Foo> is expected. Commented Feb 2, 2016 at 12:09
  • @TartanLlama after properly paying attention to the dcalaration, after you other comment, the error makes utter sense ;-). Commented Feb 2, 2016 at 12:18

2 Answers 2

2

If you want a std::vector<std::unique_ptr<Foo>> then you'll need to dynamically allocate a new Foo for each element of the array:

for( int i=0 ; i<n ; i++ ){
  vec.push_back( std::make_unique<Foo>(std::move(fooarr[i])) );
}
Sign up to request clarification or add additional context in comments.

10 Comments

Why? He could also move one unique_ptr into each element, which is what he's trying to do, or couldn't he? If not, why not?
@PeterA.Schneider The original structure is a std::unique_ptr to a single block of Foos allocated with new[] and deallocated with delete[]. The structure OP wants to change to is a collection of N std::unique_ptrs to Foos. These are completely different things.
Ah! Yes, now I see it, thanks. Do you think that misunderstanding (i.e. a mistaken definition of Foo) is the OP's problem? (" I created a unique_ptr array of Foo objects" -- why would anybody do that? :-)
@PeterA.Schneider Perhaps. Hopefully OP will comment here if they need more clarification.
@TartanLlama, Does this means that vec contains unique_ptr to the existing Foo objects and at the same time the unique_ptr array "fooarr" also still owns the same Foo objects ?
|
0

As another answer said, if you want to put Foo into vec, you should call make_unique<Foo>(std::move(fooarr[i])), if you want to put them back, you need release()

Below is the complete implementation   
class Foo
{
public:
  int id;
  Foo() {};
};
int main()
{
  int n = 10;
  std::unique_ptr<Foo[]> fooarr(new Foo[n]);
  std::vector<std::unique_ptr<Foo>> vec;
  for (int i = 0; i < n; i++)fooarr[i].id = i;
  for (int i = 0; i < n; i++) vec.push_back(make_unique<Foo>(std::move(fooarr[i])));  
  //then move back the Foo objects from vec to fooarr
  for (int i = 0; i < n; ++i) {
    fooarr[i] = *vec[i].release();
    assert(vec[i] == nullptr);  
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.