Re: operator= required for std::vector<>::push_back ??
On Feb 1, 7:04 am, Miles Bader <mi...@gnu.org> wrote:
If I have the following test file, x.cc:
#include <vector>
class X
{
public:
X (const int &_i) : i (_i) { }
X (const X &x) : i (x.i) { }
#if 0
X &operator= (const X &x)
{
if (&x != this)
new (this) X (x.i);
return *this;
}
#endif
const int &i;
};
int test ()
{
std::vector<X> xv;
int i;
xv.push_back (X (i));
}
I get an error during compilation, like:
g++ -c -o x.o x.cc
x.cc: In member function ?X& X::operator=(const X&)?:
x.cc:4: instantiated from ?void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = X, _Alloc = std::allocator<X>]?
/usr/include/c++/4.4/bits/stl_vector.h:741: instantiated from ?void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = X, _Alloc = std::allocator<X>]?
x.cc:23: instantiated from here
x.cc:4: error: non-static reference member ?const int& X::i?, can't use default assignment operator
Changing the "#if 0" to "#if 1" to define operator= makes things work.
I understand the immediate reason for the error: the g++ vector
implementation does indeed seem to call operator= on vector elements for
push_back, and in this case, the compiler-synthesized method isn't good
enough.
I would guess that in this case compiler can't emit operator= at all,
because you have a reference member.
IOW, I think that your class is not copy-able because it has a
reference member, and that is the reason why you are using ugly
"construction in operator=" trick. That is almost always unwarranted
and whoever taught you this is wrong. If you want copying, you could
just as well be using a pointer there (but expose a reference-like
semantics to users if that's what you need). There is very little, if
anything, to to gain in using a reference there.
But it somehow seems wrong that it's using operator= at all; shouldn't a
copy-constructor be enough?
Looking at the g++ STL headers, it seems like the problem is that it's
defining push_back in terms of insertion, and for the latter, you need
operator= to move elements subsequent elements to make room for a new
element. However in the case of push_back, that's really unnecessary,
and no copying of objects other than copy-constructing into new memory
when the vector's underlying storage is reallocated should be need.
Opinions? Is the error here reasonable?
Yes, it's reasonable, because push_back might need to re-allocate
storage, at which point it needs to copy existing elements to new
place. So IMO, the need to copy can be avoided only by dropping part
of push_back functionality.
Goran.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]