_Myt& operator=(const _Myt& _Right)
{ // assign _Right
if (this != &_Right)
{ // worth doing
this->_Orphan_all();
if (_Right.size() == 0)
clear(); // new sequence empty, erase existing sequence
else if (_Right.size() <= size())
{ // enough elements, copy new and destroy old
pointer _Ptr = _STD _Copy_impl(_Right._Myfirst, _Right._Mylast,
this->_Myfirst); // copy new
_Destroy(_Ptr, this->_Mylast); // destroy old
this->_Mylast = this->_Myfirst + _Right.size();
}
else if (_Right.size() <= capacity())
{ // enough room, copy and construct new
pointer _Ptr = _Right._Myfirst + size();
_STD _Copy_impl(_Right._Myfirst, _Ptr, this->_Myfirst);
this->_Mylast = _Ucopy(_Ptr, _Right._Mylast, this->_Mylast);
}
else
{ // not enough room, allocate new array and construct new
if (this->_Myfirst != 0)
{ // discard old array
_Destroy(this->_Myfirst, this->_Mylast);
this->_Alval.deallocate(this->_Myfirst,
this->_Myend - this->_Myfirst);
}
if (_Buy(_Right.size()))
this->_Mylast = _Ucopy(_Right._Myfirst, _Right._Mylast,
this->_Myfirst);
}
}
return (*this);
}
STL
Я прошу прощения, но я ничего не понимаю. Вот пишут, например, Страуструп, что библиотека зиждется не только на удобстве, но и на (в меру) быстродействии. Но кого, прошу прощения, operator = у контейнеров? Сначала clear(), а потом new? Или я ничего не понимаю? Я прошу объяснить начинающему. Или так только у Микрософт?
Цитата:
Сначала clear(), а потом new? Или я ничего не понимаю? Я прошу объяснить начинающему. Или так только у Микрософт?
а как по твоему должно производиться присваивание контейнеров?
вернее куда должны деваться элементы хранившиеся в первом контейнере до присваивания? на них же ссылки в единственном экземпляре были и хранились они в контейнере... память же нужно из-под них освобождать или как?(а все элементы хранящиеся в контейнере располагаются в куче)
п.с. а что мешает скачать gcc и посмотреть как оно там делается?
А, скажите, те, самымые, которые умные, курят? Вы попросите siziof() у любого из Ваших списочков.
вот выдранный operator= из vector в VS2010:
Код:
_Destroy(_Ptr, this->_Mylast); - если непонятно почему вызывается это - читай про кучу.
Код:
if (_Right.size() == 0)
clear();
clear();
намекает на то, что clear() вызывается в том случае, когда копируемый контейнер пуст и не нужно производить копирования новых элементов.
Код:
else if (_Right.size() <= size())
случай когда сейчас выделено больше\столько сколько надо памяти.
Код:
else if (_Right.size() <= capacity())
текущий контейнер имеет в своём распоряжении больше памяти чем занимают содержащиеся в нём элементы -> выделять ещё память не нужно.
Код:
else
{
{
текущей памяти, которой располагает контейнер, недостаточно - придётся выделить ещё.
и? ещё вопросы или ты всё таки посмотришь свежие исходники STL?
Код:
}
_Myt& operator=(const _Myt& _Right)
{ // assign _Right
if (this != &_Right)
assign(_Right.begin(), _Right.end());
return (*this);
}
template<class _Iter>
void assign(_Iter _First, _Iter _Last)
{ // assign [_First, _Last)
_Assign(_First, _Last, _Iter_cat(_First));
}
template<class _Iter>
void _Assign(_Iter _First, _Iter _Last, input_iterator_tag)
{ // assign [_First, _Last), input iterators
clear();
insert(begin(), _First, _Last);
}
_Myt& operator=(const _Myt& _Right)
{ // assign _Right
if (this != &_Right)
assign(_Right.begin(), _Right.end());
return (*this);
}
template<class _Iter>
void assign(_Iter _First, _Iter _Last)
{ // assign [_First, _Last)
_Assign(_First, _Last, _Iter_cat(_First));
}
template<class _Iter>
void _Assign(_Iter _First, _Iter _Last, input_iterator_tag)
{ // assign [_First, _Last), input iterators
clear();
insert(begin(), _First, _Last);
}
Намекает от том что, clear() вызыватся. И вопросов не задает.
судя по всему в M$ посчитали что оптимизация тут не особо нужна и сделали в лоб(учитывая то, что C++ в M$ не особо продвигается, то это не удивительно)
вот реализация operator= из библиотек g++(версия 4:4.4.3-1ubuntu1) :
Код:
130 template<typename _Tp, typename _Alloc>
131 list<_Tp, _Alloc>&
132 list<_Tp, _Alloc>::
133 operator=(const list& __x)
134 {
135 if (this != &__x)
136 {
137 iterator __first1 = begin();
138 iterator __last1 = end();
139 const_iterator __first2 = __x.begin();
140 const_iterator __last2 = __x.end();
141 for (; __first1 != __last1 && __first2 != __last2;
142 ++__first1, ++__first2)
143 *__first1 = *__first2;
144 if (__first2 == __last2)
145 erase(__first1, __last1);
146 else
147 insert(__last1, __first2, __last2);
148 }
149 return *this;
150 }
131 list<_Tp, _Alloc>&
132 list<_Tp, _Alloc>::
133 operator=(const list& __x)
134 {
135 if (this != &__x)
136 {
137 iterator __first1 = begin();
138 iterator __last1 = end();
139 const_iterator __first2 = __x.begin();
140 const_iterator __last2 = __x.end();
141 for (; __first1 != __last1 && __first2 != __last2;
142 ++__first1, ++__first2)
143 *__first1 = *__first2;
144 if (__first2 == __last2)
145 erase(__first1, __last1);
146 else
147 insert(__last1, __first2, __last2);
148 }
149 return *this;
150 }
видно, что тут оптимизирована работа с выделением памяти, так что да, не у всех сделано в лоб.
хотя... насколько часто применяется operator= ? думаю, что не оч. часто (ну нафига копировать контейнер большой? а копирование маленького врятли будет вообще заметно), следовательно на итоговую производительность это не должно сильно влиять.
Цитата:
насколько часто применяется operator= ? думаю, что не оч. часто
Очень спорно.