nm уже дал хороший ответ, но я нашел этот вопрос интересным, поэтому я решил попытаться понять его немного лучше.
Получается, когда вы звоните erase()
по первому пунктуитератор (который мы назовем item0
), вот что делает итератор: он использует оператор =
вашего класса для выполнения item0 = item1
.Затем он удаляет item1
.
Если вы не определите свой собственный оператор =
, я думаю, он просто скопирует память вашего объекта из item1
в item0
, поэтому item0
и item1
будут временно указывать на одну и ту же строку.Затем, когда item1
удаляется, строка освобождается, оставляя item0
в недопустимом состоянии, поскольку у нее есть указатель на освобожденную память.
Вот некоторый простой тестовый код, который воспроизводит и освещаетпроблема:
#include <cstring>
#include <vector>
#include <stdio.h>
using namespace std;
class Cube
{
public:
char * str;
Cube(const Cube &c) { set(c.str); }
Cube(const char * s) { set(s); }
~Cube() { clear(); } // is "delete []" necessary? not sure
#if 1 // change to 0 to cause a bug
void operator=(const Cube &c)
{
clear(); // necessary to avoid memory leaks
printf("operator=\n");
set(c.str);
}
#endif
private:
void set(const char * s)
{
str = new char[strlen(s) + 1];
printf("allocated %p for %s\n", str, s);
strcpy(str, s);
}
void clear()
{
if (str)
{
printf("freeing %p: %s\n", str, str);
delete str;
}
}
};
int main(int argc, char ** argv)
{
printf("== CREATING VECTOR ==\n");
vector <Cube> vec;
vec.push_back(Cube("octopus"));
vec.push_back(Cube("squid"));
printf("== BEGINNING ITERATION ==\n");
vector<Cube>::iterator it = vec.begin();
printf("First entry is %p %s\n", it->str, it->str);
it = vec.erase(it);
printf("Second entry is %p %s\n", it->str, it->str); // this prints garbage if Cube has no = operator
return 0;
}
Этот код производит следующий вывод:
== CREATING VECTOR ==
allocated 00350F98 for octopus
allocated 00350FB8 for octopus
freeing 00350F98: octopus
allocated 00350F98 for squid
allocated 00350FD8 for squid
allocated 00350FE8 for octopus
freeing 00350FB8: octopus
freeing 00350F98: squid
== BEGINNING ITERATION ==
First entry is 00350FE8 octopus
freeing 00350FE8: octopus
operator=
allocated 00350F98 for squid
freeing 00350FD8: squid
Second entry is 00350F98 squid
freeing 00350F98: squid
Я скомпилировал и запустил это в Windows с MinGW.Команда, которую я использовал, была g++ -Wl,--enable-auto-import test.cpp && a.exe
.