定义运算符重载时擦除向量的对象元素时出错
Error when erasing an object element of a vector when operator overloading is defined
在下面的简单示例程序中,我有一个对象向量 t_cell
,我用 5 个元素对其进行了初始化。我还有一个整数测试向量。
#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;
}
擦除元素适用于整数向量,但不适用于对象向量:
before =000
before =111
before =222
before =333
before =444
after =000
after =111
after =222
after =334
循环索引表明向量的大小已减小(现在仅从 0 变为 3)。但是第3个元素的id
没有被正确擦除
我发现问题出在运算符重载定义上。按预期删除它:
before =000
before =111
before =222
before =333
before =444
after =000
after =111
after =222
after =344
GCC 8.3.1 和 10.1.0 产生相同的行为。我编译了没有标志的代码。
operator=
的目的是改变 *this
以匹配操作数的状态,然后 return 对 *this
的引用,但这不是你的意思重新做 -- 相反,您正在创建一个 new 值并 returning 它。 returned 值被调用者立即丢弃,因此调用运算符对程序状态没有任何可观察到的影响。
更改您的代码以改变 *this
和 return 对自身的引用:
t_cell & operator = ( const t_cell &rhs_cell ){
id = rhs_cell.id;
return *this;
}
当然,在这种情况下,您的 class 是隐式可复制的,因为所有成员都是可复制的。你可以简单地不定义operator=
,编译器会为你生成一个合适的,它会做与我上面显示的运算符完全相同的事情。
在下面的简单示例程序中,我有一个对象向量 t_cell
,我用 5 个元素对其进行了初始化。我还有一个整数测试向量。
#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;
}
擦除元素适用于整数向量,但不适用于对象向量:
before =000
before =111
before =222
before =333
before =444
after =000
after =111
after =222
after =334
循环索引表明向量的大小已减小(现在仅从 0 变为 3)。但是第3个元素的id
没有被正确擦除
我发现问题出在运算符重载定义上。按预期删除它:
before =000
before =111
before =222
before =333
before =444
after =000
after =111
after =222
after =344
GCC 8.3.1 和 10.1.0 产生相同的行为。我编译了没有标志的代码。
operator=
的目的是改变 *this
以匹配操作数的状态,然后 return 对 *this
的引用,但这不是你的意思重新做 -- 相反,您正在创建一个 new 值并 returning 它。 returned 值被调用者立即丢弃,因此调用运算符对程序状态没有任何可观察到的影响。
更改您的代码以改变 *this
和 return 对自身的引用:
t_cell & operator = ( const t_cell &rhs_cell ){
id = rhs_cell.id;
return *this;
}
当然,在这种情况下,您的 class 是隐式可复制的,因为所有成员都是可复制的。你可以简单地不定义operator=
,编译器会为你生成一个合适的,它会做与我上面显示的运算符完全相同的事情。