C++ C++;释放内存的精确大小

C++ C++;释放内存的精确大小,c++,performance,list,memory,dynamic,C++,Performance,List,Memory,Dynamic,我一直在思考如何通过在程序启动时读入的(无符号)整数来提高读取列表排序的性能,该整数在程序退出之前不会更改。我考虑过不同的可能性,但后来我有了一个想法,我想知道这是否可能,如果不可能,为什么不——因为在我的理论中,计算机应该是可能的 我有一个大约有10000个条目的列表,每个条目都有一个唯一的ID(唯一ID不是0)。现在,使用sizeobject*pList=new(sizeof(object)*max_unique\u id)分配内存,然后删除所有未使用的内存(检查哪个惟一id不存在,并在大小

我一直在思考如何通过在程序启动时读入的(无符号)整数来提高读取列表排序的性能,该整数在程序退出之前不会更改。我考虑过不同的可能性,但后来我有了一个想法,我想知道这是否可能,如果不可能,为什么不——因为在我的理论中,计算机应该是可能的

我有一个大约有10000个条目的列表,每个条目都有一个唯一的ID(唯一ID不是0)。现在,使用size
object*pList=new(sizeof(object)*max_unique\u id)分配内存,然后删除所有未使用的内存(检查哪个惟一id不存在,并在大小为sizeof(object)的位置释放内存)怎么样。。。您将只使用所需的内存,只需使用
pList[unique\u id]
->访问列表条目将非常非常快。。。但是您不能删除动态分配数组中的单个元素:/在程序终止时,您当然可以释放所有元素,在std::vector或类似的东西中保护指针+大小是没有问题的


这就是为什么我要问我的理论是否错误,或者系统是否不允许,或者问题在哪里。

不,你不能那样控制内存。然而,有可能会有一点欺骗。如果要分配大块内存,可以创建自己的内存池。这样,您就可以自己创建洞,并将该内存用于程序的其他部分

不过,我不推荐这样做,因为您可能会遇到严格的别名问题,并且必须处理代码中更复杂的问题

稍微倒带一下,您就忘记了缓存效果,这是非常重要的。将对象紧密地组合在一起可能比加快查找速度对速度的影响更大

要实现这一点,您可以使用一个简单的散列来查找对象,也可以只创建一个由16位索引组成的稀疏索引数组。

您可以(虽然我不知道为什么要这样做),但您必须将其编写为您自己的自定义内存分配和释放例程或类。使用标准C++库外,你不能。

<>参见C++中的内存分配接口
void* operator new  ( std::size_t );
void* operator new[]( std::size_t );
void* operator new  ( std::size_t, const std::nothrow_t&);
void* operator new[]( std::size_t, const std::nothrow_t&);
采用
void*运算符新[](std::size\u t)例如。这个例程绝对不可能知道将返回的内存区域中存储了多少对象

与它的匹配函数相同

 void operator delete[]( void* ptr );
它只需要一个
void
指针,绝对不可能知道要删除多少。提供以
ptr
指向的块开始的内存的内存分配器知道它分配的大小,因此会适当地删除它

使用
placement new

不要这样做。
new
不是
malloc
。但你也不能这样做:

object* pList = new object[max_unique_id];
delete object[1];
C++不允许使用简单的
delete
删除动态分配数组中单独分配的元素

C++允许您使用
placement new
在预先分配的内存空间中创建对象。在这种情况下,您必须通过调用placement new和析构函数手动调用构造函数

参考:

换言之,提供要创建特定对象的确切位置。我建议您使用循环:

// Allocate the space using malloc()
object* pList = std::malloc(sizeof(object) * max_unique_id);

// Allocate using a loop. I would not trust a parallelization of this code.
// Doing memory allocation in parallel without the proper locks and stuff
// is probably wrong.
for (auto i = 0; i < max_unique_id; ++i) {
  // Supply the point as the argument to placement new.
  new (&pList[i]) object(/* arguments go here */);
}

我使用的是C++风格的C标准库中定义的
std::malloc()
std::free()

我认为这方面的主要问题是:以后你怎么知道,哪些元素仍然存在,哪些元素被释放?您无法控制针对操作系统的请求将分配或释放哪些内存块。没错,Anedar,这是我理论中的主要问题。。我也考虑过这一点,到目前为止还没有找到一个真正好的解决方案。^^不知何故,您需要确保程序只访问现有元素。。好吧,但撇开这一点不谈——理论上这是可能的,不是吗?所以,仅仅因为系统没有给你删除精确大小内存的自由,你就不能这么做——是吗?目前,我想知道它是否能够在没有操作系统限制的情况下工作^^@Crispy您可以查找placement
new
,尽管您无法针对操作系统实现细粒度内存分配控制。您的第一个瓶颈是读取文件,而不是内存分配。您希望直接将尽可能多的内容读入内存,然后将其移动到列表中。这会加快执行时间。你完全正确,OP的想法对性能非常糟糕。与分散的内存访问相比,算术是便宜的。但是,如果您将自己限制为可移植的C++ +代码>新的< /代码> /<代码>删除< /COD>或<代码> Malc > /COD> > />代码> ReLoC/ <代码>免费< /COD>,则您的声明是唯一正确的。在POSIX系统(例如Linux)上,您可以使用
mmap(MAP\u FIXED)
仅在需要时分配页面。或者(让操作系统找到一个未使用的虚拟地址范围),
mmap
通常是一个巨大的分配,然后
munmap
使用索引之间的所有漏洞。感谢您提供的额外信息。希望OP不会决定使用
mmap
munmap
A* a = (A*)malloc(sizeof(A));
new (a) A();

a->~A();
free(a);
// Allocate the space using malloc()
object* pList = std::malloc(sizeof(object) * max_unique_id);

// Allocate using a loop. I would not trust a parallelization of this code.
// Doing memory allocation in parallel without the proper locks and stuff
// is probably wrong.
for (auto i = 0; i < max_unique_id; ++i) {
  // Supply the point as the argument to placement new.
  new (&pList[i]) object(/* arguments go here */);
}
// Select the object
object* todelete_object = pList[i];
// Manually call the destructor.
todelete_object->~object()
// Now, free the memory.
std::free(todelete_object);