Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert into vector having objects without copy constructor

Tags:

I have a class whose copy constructors are explicitly deleted (because A uses pointers internally and I don't want to fall into shallow copy pitfalls):

class A {   public:     A(const A&) = delete;     A& operator=(const A&) = delete;      A(const B& b, const C& c); } 

Now I have a vector of type vector<A> aVector; and I want to insert elements into it - so I use emplace_back:

aVector.emplace_back(b, c); 

However, this fails to compile using gcc and I get the error -

third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:77:3:   required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator)   third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:119:41:   required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator)  third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:260:63:   required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&)  third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:283:67:   required from '_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/vector.tcc:410:6:   required from 'void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...)  third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/vector.tcc:102:4:   required from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) 

What is the reason for this error and how can it be fixed without removing the deletion of the copy constructors? Do I need a move constructor - does it need to be explicitly defined?

like image 579
vigs1990 Avatar asked Nov 07 '13 01:11

vigs1990


People also ask

Does vector insert make a copy?

If you dereference the pointer and push the result onto a std::vector<T> , then a copy of the object is made. Collections always make copies.

What happens if you use the default copy constructor for vector?

The default copy constructor will copy all members – i.e. call their respective copy constructors. So yes, a std::vector (being nothing special as far as C++ is concerned) will be duly copied.

Why is object's reference passed to the copy constructor instead of the object itself?

It is necessary to pass object as reference and not by value because if you pass it by value its copy is constructed using the copy constructor. This means the copy constructor would call itself to make copy. This process will go on until the compiler runs out of memory.

Should I use std for vector?

If you need a "dynamic" array, then std::vector is the natural solution. It should in general be the default container for everything. But if you want a statically sized array created at time of compilation (like a C-style array is) but wrapped in a nice C++ object then std::array might be a better choice.


1 Answers

You should add move constructor - because std::vector::emplace_back may do relocation which requires copy/move constructor. Or just use std::deque.

LIVE DEMO

#include <vector> #include <deque> using namespace std;  struct NoCopyNoMove {     NoCopyNoMove(const NoCopyNoMove&) = delete;     NoCopyNoMove& operator=(const NoCopyNoMove&) = delete;     NoCopyNoMove(NoCopyNoMove&&) = delete;     NoCopyNoMove& operator=(NoCopyNoMove&&) = delete;      NoCopyNoMove(int){}; };  struct OnlyMove {     OnlyMove(const OnlyMove&) = delete;     OnlyMove& operator=(const OnlyMove&) = delete;     OnlyMove(OnlyMove&&) noexcept {}     OnlyMove& operator=(OnlyMove&&) noexcept {}      OnlyMove(int){}; };  int main() {     deque<NoCopyNoMove> x;     x.emplace_back(1);      vector<OnlyMove> y;     y.emplace_back(1); } 

§ 23.2.3 Table 101 — Optional sequence container operations

a.emplace_back(args) [...]

Requires: T shall be EmplaceConstructible into X from args. For vector, T shall also be MoveInsertable into X.

like image 116
Evgeny Panasyuk Avatar answered Oct 01 '22 01:10

Evgeny Panasyuk