简体   繁体   中英

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM