如果std :: vector元素'自杀'会发生什么(使用delete this;)?

ris*_*nrp 3 c++ vector self-destruction

假设有一个Items 向量

vector<Item*> items; //{item1, item2, item3}
Run Code Online (Sandbox Code Playgroud)

然后,在代码的其他部分,

items[1]->suicide();
Run Code Online (Sandbox Code Playgroud)

其中suicide函数为:

void Item::suicide()
{
   delete this;
}
Run Code Online (Sandbox Code Playgroud)

什么是items矢量大小以及它现在的排列方式?这是做呢?

编辑(我可以问一个额外的问题吗?):如果输出的所需排列是{item1, item3},大小是2,并且没有悬空指针,如何以自毁方式(从它item2自身)进行?

编辑2:谢谢你的所有答案!真棒.所以我最终决定并找到了从对象外部做到这一点的方法,因为这是一种不好的做法而且不必要地复杂化

Ral*_*zky 6

什么是项目矢量大小以及它现在的排列方式?相同.函数调用根本不会改变矢量内容或大小.它只是释放指针指向的内存.

这样做可以吗?更确切地说:它是合法的C++吗?是.这是好的风格编程吗?不,请允许我详细说明后者:

  • 关注点应该分开:谁负责内存管理?容器或类的用户Item或类Item本身?

  • 通常,容器或用户应该这样做,因为他知道发生了什么.

  • 这样做的方法是什么?在现代,安全的C++代码中的内存管理是使用智能指针像大部分完成std::shared_ptr,并std::unique_ptr和容器,如std::vectorstd::map.

  • 如果类Item是值类型(这意味着您可以简单地复制它并且它在虚函数方面没有多态行为),那么只需使用std::vector<Item>代码即可.一旦从容器中删除元素,就会自动调用析构函数.容器为你做.

  • 如果类Item具有多态行为并且可以用作基类,那么使用std::vector<std::unique_ptr<Item>>std::vector<std::shrared_ptr<Item>>替代并优先选择std::unique_ptr解决方案,因为它增加了开销.只要您停止引用某个对象,它就会被您正在使用的智能指针的析构函数自动删除.你(几乎)不再需要担心内存泄漏了.

  • 产生内存泄漏的唯一方法是,您拥有包含std::shared_ptrs以循环方式相互引用的对象.使用std::unique_ptrs可以防止这种麻烦.另一种出路是std::weak_ptrs.

底线:不提供功能suicide().而是将责任完全交给调用代码.使用标准库容器和智能指针来管理内存.

编辑:关于编辑中的问题.写吧

items.erase( items.begin() + 1 );
Run Code Online (Sandbox Code Playgroud)

这适用于所有类型:std::vector值或指针.您可以在此处找到std::vectorC++标准库的良好文档.


APr*_*mer 5

自杀成员不会改变矢量.因此,向量包含一个无效指针的元素,并且形式上你无法用无效指针做很多事情,即使复制或比较它也是未定义的行为.所以访问它的任何东西,包括矢量大小调整,都是一个UB.

如果正式UB的任何访问,只要你不取消引用指针,你的实现很可能不会表现得很奇怪 - 进行任何访问的理由UB是在寄存器中加载无效指针的机器可以陷阱和x86是其中的一部分,我不知道在这种模式下工作的广泛操作系统.