4 ms·
> This is precisely what vector::emplace() solves, and std::move should be faster than swap and pop. The whole swap-and-pop section weirded me out. Maybe I jus
by CodeMage 7y ago
> This is precisely what vector::emplace() solves, and std::move should be faster than swap and pop.
The whole swap-and-pop section weirded me out. Maybe I just don't know enough about C++, but saying that assignment (a[i] = a[n-1]) will call the destructor seems false.
As far as I know, the compiler should generate an implicitly defined copy assignment operator for these fixed size PODs and it should be as performant as memcpy.
But again, I don't have years and years of in-depth C++ experience, so I would be grateful if an expert could shed more light on this.
- foota 7y agoYeah, fairly certain that is wrong. I think that would just call the copy assignment operator, would it not? For correctness you would probably then follow up with a pop_back to keep the vector right-sized. Actually you'd probably want to do: a[i] = std::move(a[n - 1]); Then follow up with pop_back. Best would probably be: a[i] = std::move(a.erase(n-1));
- hermitdev 7y agoIdeally, the std lib implementation should handle that detail for you...
- gpderetta 7y agowhich detail?
- foota 7y agoIn theory erase could return a move iterator, meaning that you could omit the call to std::move. This wouldn't be backwards compatible though so not going to happen.
- gpderetta 7y agowait, how is this supposed to work? a[i] = std::move(a.erase(n-1)); There is no erase that takes an index, so I assume that n = a.end(). Also it is missing a dereference: a[i] = std::move(*a.erase(a.end()-1)); but erasing the one-before-the-end returns the (new) end iterator, which obviously is not referenceable. In general, after calling erase, it is too late to access the erased element. You want something like: template<class Container, class Iter> auto erase_and_return(Container&& c, Iter pos) { auto x = std::move(*pos); c.erase(pos); return x; } Also in the general case it doesn't make sense for erase to return a move iterator.
- foota 7y agoThanks for the corrections. I mis-read the documentation and thought erase returned an iterator to the elements erased.
- lenkite 7y agoYou are correct. A trivial copy assignment operator makes a copy of the object representation as if by std::memmove. All data types compatible with the C language (POD types) are trivially copy-assignable. https://en.cppreference.com/w/cpp/string/byte/memmove https://en.cppreference.com/w/cpp/string/byte/memmove
- rurban 7y agoNot memmove. A trivial object assignment can be _memcpy_aligned, which is much faster. And the size is compile-time constant.
- lenkite 7y agoI assume you mean aligned on boundaries ? I picked up that from https://en.cppreference.com/w/cpp/language/copy_assignment https://en.cppreference.com/w/cpp/language/copy_assignment and it does also say that memmove has a fallback to std::memcp when there is no overlap between source and destination.