Does std::vector<Object> reserve method need a copy constructor for Object class?

c++, c++11, vector

Solution

   std::vector<Foo> fooVector;
   fooVector.reserve(20); // Error

   for(int i=0; i<20; i++){
       fooVector[i] = Foo("Test", i); // Or should I use operator new?
       // Or should I even stick to the push_back method?
   }

The code above is wrong. You are accessing elements beyond `size()` in the container. The idiomatic way of doing that would be doing `push_back`/`emplace_back` on the container to actually create the objects, rather than only memory:

   for(int i=0; i<20; i++){
       fooVector.emplace_back("Test", i);  // Alternatively 'push_back'
   }

Other than that, in C++11 the type used in the container requires either a copy or move constructor.

Problem

I'm trying to reserve some spots into an std::vector, and having an error I don't understand: ``` #include <iostream> #include <string> #include <vector> using namespace std; class Foo{ public: std::string str; int i; Foo(){ this->str = ""; this->i = 0; } Foo(Foo &copyFoo){ this->str = copyFoo.str; //Or get methods if private members this->i = copyFoo.i; } Foo(std::string str, int i){ this->str = str; this->i = i; } }; int main() { std::vector<Foo> fooVector; fooVector.reserve(20); // Error for(int i=0; i<20; i++){ fooVector[i] = Foo("Test", i); // Or should I use operator new? // Or should I even stick to the push_back method? } return 0; } ``` Of course I could just not reserve, and it would probably work. But now I'm interested in why it is not working now. I added the copy constructor because it looked that could be the problem I was having back then. But after adding the copy constructor, it doesn't work either. The error says: In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/vector:62:0, ``` from main.cpp:3: /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_construct.h: In ``` instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = Foo; _Args = {Foo}]': /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_uninitialized.h:75:53: required from 'static _ForwardIterator std::__uninitialized_copy<TrivialValueTypes>::_uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = Foo*; bool _TrivialValueTypes = false]' /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_uninitialized.h:117:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = Foo*]' /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_uninitialized.h:258:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator; _ForwardIterator = Foo*; _Tp = Foo]' /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_vector.h:1142:29: required from 'std::vector<_Tp, _Alloc>::pointer std::vector<_Tp, _Alloc>::_M_allocate_and_copy(std::vector<_Tp, _Alloc>::size_type, _ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::move_iterator; _Tp = Foo; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::pointer = Foo*; std::vector<_Tp, _Alloc>::size_type = long unsigned int]' /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/vector.tcc:75:70: required from 'void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = Foo; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::size_type = long unsigned int]' main.cpp:31:24: required from here /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_construct.h:75:7: error: no matching function for call to 'Foo::Foo(Foo)' ``` { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } ^ /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_construct.h:75:7: ``` note: candidates are: main.cpp:22:5: note: Foo::Foo(std::string, int) ``` Foo(std::string str, int i){ ^ main.cpp:22:5: note: candidate expects 2 arguments, 1 provided main.cpp:17:5: note: Foo::Foo(Foo&) Foo(Foo &copyFoo){ ^ main.cpp:17:5: note: no known conversion for argument 1 from 'Foo' to 'Foo&' main.cpp:12:5: note: Foo::Foo() Foo(){ ^ main.cpp:12:5: note: candidate expects 0 arguments, 1 provided ``` Where is the problem? Do I need to initialize the std:vector objects, or just assign each position to an object instance? EDIT: I'm using C++11. And If I remove the copy constructor, I receive the following error at the reserve method line: ``` required from 'void std::_Construct(_T1*, _Args&& ---) [with _TI = Foo; _Args = {Foo&}] ``` That's why I wrote the copy constructor in the first place. I don't want to use the resize method because I want the size method to return the actual number of Foo objects contained into the vector, not the amount I reserved.

Original source

Related problems