Take the 2-minute tour ×

Running the following test code

int destroyed[3] = { 0, 0, 0 };

struct Test {
    int a;
    Test() {}
    ~Test() {

template<class T>
void remove(std::vector<T>& v, size_t i) {
    std::swap(v[i], v.back());

main() {
    std::vector<Test> vt(3);
    vt[0].a = 0;
    vt[1].a = 1;
    vt[2].a = 2;
    remove(vt, 0);

destroyed counts the number of times an element has been destroyed.

I can see that destroyed = { 2, 0, 0 }.

I want to remove element 0, so I should destroy it. However I don't need to call its destructor twice; so, how can I write the remove function so that I end up with destroyed = { 1, 0, 0 } (destroying it only once)?

share|improve this question
Write a move constructor for Test. –  Ben Apr 14 at 3:46
The Test class is only for testing the remove function. remove should behave correctly for every class. –  Inuart Apr 14 at 3:51
Because std::swap(v[i], v.back()); doesn't find a move constructor or swap specialisation, it falls back on copying v[i=0] to a temporary so it can overwrite it with v.back() then assign v.back() from the temporary. The temporary will have a == 0 due to the default copy-constructor, so when its destructor runs it increments destroyed[0]. Later, v.back()'s destructor increments it again. Tell the compiler how to swap Test objects without a temporary, or add move for Test that puts the moved object into special state (e.g. a = -1) then if (a != -1) ++destroyed[a]. –  Tony D Apr 14 at 3:54
Yeah, it is behaving correctly. When you call std::swap on two elements, there's copying going on. When c++ copies an object, it doesn't move it from one place to another, it destroys it in one place and recreates it at another. Now, if your class T had a move constructor, the std::vector could use that to MOVE the object around, rather than copy it. –  Ben Apr 14 at 3:55
I suggest you count constructors as well as destructors, and don't forget copy construction. You will find that the books do balance. –  EJP Apr 14 at 4:22

1 Answer 1

up vote 0 down vote accepted

This implementation of remove seems to work

template<class T>
    uint8_t d[sizeof T];
    memcpy(d, &v[i], sizeof T);
    v[i] = v.back();
    memcpy(&v.back(), d, sizeof T);

Comments on this code will be very appreciated.

share|improve this answer

Your Answer


