Ответ 1
Когда вы вводите оператор kill
, m[1]
(from m[1].kill(m, 1);
), он был полностью оценен как объект foo
, который вы вызываете kill
on.
Затем вы выполняете m.erase(i);
в результате уничтожения текущего объекта foo
.
Насколько вы пишете абсолютно никакой оператор, использующий текущий объект (this
), прежде чем вы вернетесь из функции kill
, это совершенно приемлемо и безопасно (как прокомментировали сообщения, на которые ссылается Auriga и Barry). Даже если текущий объект больше не существует, ваша функция будет безопасно возвращаться из стека, нет причин для его отказа, насколько мне известно.
В качестве иллюстрации это приведет к поведению undefined и НЕ должно быть выполнено:
struct foo
{
void kill(std::map<int, foo>& m, int i)
{
m.erase(i);
cout << attribute; // don't do that! current foo object does not exist anymore
}
int attribute;
};
Итак, скажите, что вы делаете, это рискованно, но действительно и безопасно, если вы это сделаете хорошо.
В качестве иллюстрации это приведет к определенному поведению и CAN BE DONE:
struct foo
{
void kill(std::map<int, foo>& m, int i)
{
int theAttribute = attribute;
m.erase(i);
cout << theAttribute; // OK!
}
int attribute;
};
Наличие метода удаления текущего объекта в любом случае, вероятно, не является хорошей практикой (особенно, если другой разработчик позже модифицирует код... он может легко заставить его сбой с первого примера выше). По крайней мере, поместите явный комментарий в код, чтобы сообщить, что текущий объект мог быть уничтожен (обратите внимание, что kill
может уничтожить текущий объект, другой или нет... в зависимости от содержимого m
и i
):
struct foo
{
void kill(std::map<int, foo>& m, int i)
{
m.erase(i);
// careful! current object could have been destroyed by above statement and may not be valid anymore! Don't use it anymore!
}
};