TransWikia.com

Error when erasing an object element of a vector when operator overloading is defined

Stack Overflow Asked by solalito on December 18, 2021

In the simple example program below, I have a vector of objects t_cell which I initialize with 5 elements. I also have a test vector of integers.

#include <iostream>
#include <iomanip>
#include <vector>

using namespace std;

class t_cell {
    public:
        int id;

    t_cell operator = ( const t_cell &rhs_cell ){
        t_cell lhs_cell;
        lhs_cell.id = rhs_cell.id;
        return lhs_cell;
    }
};


int main(){

    std::vector<int   > test ( 5 );
    std::vector<t_cell> cells( 5 );

    for( size_t icell=0; icell < cells.size(); icell++ ){
        test [icell]    = icell;
        cells[icell].id = icell;
    }

    for( size_t icell=0; icell < cells.size(); icell++ ){
        cout << "before =" << icell << test [icell] << cells[icell].id << endl;
    }
    cout << endl;

    // Erase
    cells.erase( cells.begin() + 3 );
    test .erase( test .begin() + 3 );

    for( size_t icell=0; icell < cells.size(); icell++ ){
        cout << "after  =" << icell << cells[icell].id << test [icell] << endl;
    }

    return 0;
}

Erasing the element works with the integer vector but not with the vector of objects:

before =000
before =111
before =222
before =333
before =444

after  =000
after  =111
after  =222
after  =334

The loop index indicates that the vectors have been reduced in size (only goes from 0 to 3 now). However, the id of the 3rd element has not been erased properly.

I’ve found that the issue comes from the operator overloading definition. Removing that works as intended:

before =000
before =111
before =222
before =333
before =444

after  =000
after  =111
after  =222
after  =344

Both GCC 8.3.1 and 10.1.0 yields the same behavior. I’ve compiled the code without flags.

One Answer

The purpose of operator= is to change *this to match the state of the operand and then return a reference to *this, but that's not what you're doing -- instead, you are creating a new value and returning it. The returned value is promptly discarded by the caller, and so invoking the operator doesn't have any observable effect on the state of the program.

Change your code to mutate *this and return a reference to itself:

t_cell & operator = ( const t_cell &rhs_cell ){
    id = rhs_cell.id;
    return *this;
}

Of course, in this case your class is implicitly copyable since all of the members are copyable. You can simply not define operator= and the compiler will generate a suitable one for you, which will do exactly the same thing as the operator I've shown above.

Answered by cdhowie on December 18, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP