gpt4 book ai didi

c++ - 在 std::erase() 产生未定义行为之前调用 std::fill() 吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:12:59 25 4
gpt4 key购买 nike

我正在开发一个 C++11 程序,其中安全性很重要,我的任务是在删除后将已用内存设置为 0。

我有一个 std::map 从 int 映射到 指向类的指针std::vector。我在 std::map 中有索引和指向我想删除的实例的指针。

下面的代码产生了我想要的输出,但是,我不确定它是否是格式正确的代码(或者我会说我不确定这段代码是否正确)。

我有 2 个问题。

  1. 如果下面的代码没问题,
  2. 只能用-fpermissive编译,我不明白编译错误信息。
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>


class MyClass
{
private:
int num;
public:
MyClass(int num) { this->num = num; }
int GetNum() const { return this->num; }
};


void PrintWorkingData(const std::map<int, std::vector<MyClass*>>& working_data, int idx)
{
std::cout << "working_data[" << idx << "] is an std::vector, size: " << working_data[idx].size() << ", containing the following items: " << std::endl;
for (std::vector<MyClass*>::const_iterator it = working_data[idx].begin(); it != working_data[idx].end(); it++)
{
std::cout << "(*it)->GetNum() = " << (*it)->GetNum() << std::endl;
}
}


int main()
{
MyClass* DeleteMyClass;

std::map<int, std::vector<MyClass*>> working_data;
working_data[0].push_back(new MyClass{4});
working_data[0].push_back(new MyClass{7});
working_data[1].push_back(new MyClass{11});

// the origonal code isn't like this; let's suppose
// we stored in the DeleteMyClass pointer the MyClass pointer
// that we would like to delete
working_data[1].push_back(DeleteMyClass = new MyClass{22});

working_data[1].push_back(new MyClass{33});
working_data[2].push_back(new MyClass{1000});

PrintWorkingData(working_data, 0);
PrintWorkingData(working_data, 1);
PrintWorkingData(working_data, 2);
PrintWorkingData(working_data, 3);

// so our task is to delete DeleteMyClass object from working_data[DeleteItemIndex]
// and fill with 0 where it was stored
int DeleteItemIndex = 1;

std::vector<MyClass*>::iterator pos = std::find(working_data[DeleteItemIndex].begin(), working_data[DeleteItemIndex].end(), DeleteMyClass);
if (pos == working_data[DeleteItemIndex].end())
{
std::cout << "Error: The item does not present in the working_data" << std::endl;
}
else
{
std::fill(pos, pos + 1, 0);
working_data[DeleteItemIndex].erase(pos);
delete DeleteMyClass;
std::cout << "The object successfully deleted" << std::endl;
}

PrintWorkingData(working_data, 0);
PrintWorkingData(working_data, 1);
PrintWorkingData(working_data, 2);
PrintWorkingData(working_data, 3);

return 0;
}

最佳答案

将指针值设置为 nullptr 不会更改它指向的数据。从 vector 中删除一个元素将用 vector 中所有后面的元素覆盖该元素,在分配的内存中(在这种情况下)留下第二个指针(超出 vector 的大小)指向 vector 中的最后一个元素。

要删除DeleteMyClass 指向的对象占用的内存,您必须分别处理对象销毁和内存释放。这不一定简单或直接,因为可能存在需要解决的细微差别(异常处理、数组与非数组形式)。您还应该记住,可以检查正在运行的进程的内存,并在使用它的对象处于事件状态时查看您试图删除的数据。

这里有几种方法可能适合您的情况。

一种方法是手动调用析构函数,清除内存,然后释放它。

DeleteMyClass->~MyClass();
memset(DeleteMyClass, 0, sizeof(*DeleteMyClass));
delete (void *) DeleteMyClass;

delete 调用上的强制转换是避免调用析构函数所必需的,要清除的字节数使用 DeleteMyClass 的类型,如果指向的是派生类,这将是不正确的来自 MyClass

另一种选择是使用 placement new使用已分配的内存缓冲区和自定义释放器(在手动调用析构函数后)来释放内存。

第三种可能性是使用 custom newdelete功能,无论是针对这个特定类还是全局。

关于c++ - 在 std::erase() 产生未定义行为之前调用 std::fill() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55987482/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com