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

标签 c++ algorithm memory stl fill

我正在开发一个 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/

相关文章:

c++ - GLSL 日志返回未定义的结果

java - 给定 'getrand100()' 函数获取特定范围内的随机数

java - 在 Java 中比较两个表列值

c++ - 通过 new[] 分配 n 个字节并用任何类型填充它?

c - 错误 `./px' : free(): invalid next size (normal)Aborted (core dumped)

c++ - 如何在二叉搜索树中查找元素?

c++ - 没有在类 'void StringSet::removeALL()' 中声明的 'StringSet' 成员函数

c++ - 最少的 openGL 初始化

算法 : random unique string

flash - 为什么Flash要乘以8?