从地图中删除指向已删除对象的所有条目
Removing all the entries pointing to a deleted object from a map
所以这是我正在处理的代码:
class A
{
public:
A(){}
virtual ~A(){}
void Log(){printf("Log An");}
};
int main(int argc, char**argv)
{
A* a = new A();
a->Log(); // "Log A"
map<int,A*> m;
m[1] = a;
m[2] = a;
m[3] = a;
m[1]->Log(); // "Log A"
delete a;
a = NULL;
m[1]->Log(); // "Log A"
return 0;
}
输出:
日志 A
日志 A
日志 A
我的问题:
- 调用
m[1]->Log()
在delete a
后不会引发异常只是偶然的吗? - 擦除映射中指向已删除
A
实例的所有条目的最佳方法是什么?我的意思是我希望所有m.find(1)
、m.find(2)
和m.find(3)
在删除a
后返回m.end()
。任何建议将不胜感激。
-
是和不是。从技术上讲,这是未定义的行为,但通常(不依赖于此)调用不访问成员的非虚拟方法似乎适用于大多数编译器,因为大多数编译器在不取消引用
this
的情况下实现此调用(这是无效部分)。所以,在标准看来,这是偶然的。对于大多数编译器来说,这是有意的(或者至少是如何处理函数调用的副作用)。 -
请改用智能指针。要删除元素,您可以循环访问地图并将每个值与您的值进行比较。当您达到一个时,请使用
erase
.
-
取消引用已删除对象时发生的任何事情都是未定义的行为,因此即使获得异常也可能被认为是"偶然"
-
最好的方法是将指向的对象的删除与你拥有句柄的内容的生存期结合起来。因此,在您的情况下,您可以决定最好从地图中删除指针,则删除对象。为此,您可以使用 int 映射来std::unique_ptr<A>
而不是原始指针之一。
编辑:在更详细地查看要求后:
现在,由于您要删除映射类型指向已删除对象的元素,并且无法确定指针指向的内存是否已被删除,因此除了在一次函数调用中完成所有操作之外,我认为没有简单的方法可以从映射中删除这些条目。由于std::map
等人不喜欢std::remove_if
,可以使用循环:
template <typename T1, typename T2>
void removeEntriesAndDelete(std::map<T1, T2*>& m, T2*& item) {
for (auto i = m.begin(); i != m.end(); ) {
if ( item == i->second) {
m.erase(i++);
} else {
++i;
}
}
delete item;
item=0;
}
int main() {
A* a = new A;
std::map<int,A*> m;
m[1] = a;
m[2] = a;
m[3] = a;
std::cout << std::boolalpha;
std::cout << a << ", " << bool(m[1]) << ", " << bool(m[2]) << ", " << bool(m[3]) <<"n";
removeEntriesandDelete(m, a);
std::cout << a << ", " << bool(m[1]) << ", " << bool(m[2]) << ", " << bool(m[3]) <<"n";
}
通常,在某处注册的对象必须通知对象在哪里他们已注册。 在像您的示例代码这样的简单情况下,它是相对简单的浏览地图,擦除每个元素指向您的对象,但我假设您的实际用例较少琐碎。 通常的解决方案(实际上,唯一真正有效的解决方案在实践中)涉及观察者模式;当对象保存指向对象的指针,直接或在地图或列表中,或无论如何,它还会注册您的对象,在以下情况下请求通知您的对象被销毁。 您的对象保留了这些观察者的列表,并将在其析构函数中通知他们。 应用于一个简单的情况,如你的,它看起来像很多不必要的代码,但在发生这种模式的实际应用程序,它并不多。
正如你提到的,它靠运气工作。
使用前面提到的智能指针之类的东西,或者将映射和值处理封装在一个类中,您可以在类中有一个从映射中删除对象并删除对象的方法。
- 迭代时从向量和内存中删除对象
- C++从对象自己的类中删除对象
- 如何通过对象的类属性删除对象,并返回其对象值?
- 删除对象(具有不同类型)的引用时会发生什么情况?
- 从列表C++中删除对象
- c++ 循环访问对象列表并删除对象
- 从对象本身的容器中删除对象
- 从尝试引用已删除函数的矢量 C++ 中删除对象
- 如何通过指向元组的共享指针删除对象
- 防止通过接口删除对象
- 在 c++ 中从内存中删除对象
- 当对象被删除时,复制被删除对象的对象如何
- 当我使用dynamic_cast并删除对象删除时,析构函数是如何工作的?
- 从内存中删除对象
- 通过C++中的删除方法自行删除对象
- C++ - 析构函数只是释放内存还是实际删除对象
- 如何通过存储在 std::list 中的指针删除对象?
- 如何通过对象参数从指针矢量中删除对象和指针
- 我可以删除对象的右值版本的函数吗?
- 使用对象的索引从矢量中删除对象