gpt4 book ai didi

c++ - 通过一次调用 new 运算符来批量分配对象?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:04:42 24 4
gpt4 key购买 nike

我了解有关为特定类重载 new 运算符的基础知识。但是,如果可能的话,我不明白一件事。假设我有这样的类(class):

class X{
int a;
long b;
float c;
}

我希望在我的程序一开始就预先创建 100 个 X 对象。我想只调用一次新运算符,分配(至少)(4 + 4 + 4?)x 100 = 1200 字节。然后,每当 X::new() 被调用,而不是 new() ( 或 malloc())被调用时,我将返回X 对象的空“外壳”,然后是 abc 被简单地分配给数据成员。

我该怎么做呢?我的问题的重点是当我为 100 个 X 对象保留 1200 个字节时,内存只从内核中获取一次。在我的程序开始后,我希望在检索 X 对象“shell”时执行最低限度的操作?

最佳答案

The emphasis on my question is that memory is only taken from the kernel once, when I reserve 1200 bytes for 100 X objects. After the beginning of my program I want the bare minimum to be executed when retrieving an X object "shell"?

听起来您正在尝试做的事情类似于构建一个 memory pool .

在内存池中,您预先分配了一个大型原始缓冲区,对象最终将存放在该缓冲区中。稍后您将在此缓冲区中分配各个对象。这样做的好处是不必为每个单独的对象分配内存——您所要做的就是在预先分配的空间内构造对象。由于您不必为每个以这种方式实例化的 Object 深入内核,因此可能会节省大量时间。缺点是您负责以更直接的方式管理这些对象。代码可能很棘手、复杂且容易出错。

要分配原始缓冲区,我们只需分配一个足够大的 char 数组来容纳所有预期的 Object:

char* buf = new char [1200];

为了完成第二部分——在内存池中构造一个对象——你需要使用placement-new。 .假设 buf 是预分配缓冲区中您希望构建新对象 p 的位置:

Object* p = new (buf) Object();

当需要销毁这个对象时,不要使用deletedelete 将尝试为对象解除分配内存,从而产生未定义的行为并可能发生崩溃,因为您没有为对象1 分配内存。相反,这是一种您必须直接调用析构函数的情况:

p->~Object();

一旦所有对象都被销毁,您就可以使用delete[]释放缓冲区:

delete [] buf;

这里是一个完整的例子,展示了如何使用 placement-new,包括缓冲区的构建。这使用(隐式定义的)默认构造函数。稍后我将展示如何使用另一个构造函数:

#include <cstdlib>
#include <new> // required for placement-new
#include <iostream>


class X
{
public:
int a;
long b;
float c;
};

int main()
{
// construct the memory pool's buffer
char* buf = new char [sizeof(X) * 1000]; // enough memory for 1000 instances of X

// Instantiate 1000 instances of X using placement-new
for (size_t i = 0; i < 1000; ++i)
{
// Where in the memory pool shoudl we put this?
char* buf_loc = buf + (sizeof(X) * i);
// Construct a new X at buf_loc
X* new_x = new (buf_loc) X;
}


// Do something with those instances
for (size_t i = 0; i < 1000; ++i)
{
// Where is the object?
char* buf_loc = buf + (sizeof(X) * i);
X* my_x = reinterpret_cast <X*> (buf_loc); // this cast is safe because I *know* that buf_loc points to an X

// Let's assign some values and dump them to screen
my_x->a = i;
my_x->b = 420000 + i;
my_x->c = static_cast <float> (i) + 0.42;

std::cout << "[" << i << "]\t" << my_x->a << "\t" << my_x->b << "\t" << my_x->c << "\n";
}

// Destroy the X's
for (size_t i = 0; i < 1000; ++i)
{
// Where is the object?
char* buf_loc = buf + (sizeof(X) * i);
X* my_x = reinterpret_cast <X*> (buf_loc); // this cast is safe because I *know* that buf_loc points to an X

// Destroy it
my_x->~X();
}

// Delete the memory pool
delete [] buf;
}

现在让我们为 X 定义一个带参数的构造函数:

class X
{
public:
X (int aa, long bb, float cc)
:
a (aa),
b (bb),
c (cc)
{
}
int a;
long b;
float c;
};

由于我们在这里定义了一个构造函数,编译器将不再为 X 隐式定义一个默认构造函数

让我们使用这个新的构造函数。现在必须传递构造函数的参数:

   // Instantiate 1000 instances of X using placement-new
for (size_t i = 0; i < 1000; ++i)
{
// Where in the memory pool shoudl we put this?
char* buf_loc = buf + (sizeof(X) * i);
// Construct a new X at buf_loc
X* new_x = new (buf_loc) X(0,0,0.0f);
}

不要使用 delete1:从技术上讲,这里使用 delete 会产生 undefined行为 是因为delete 只能使用从调用new 返回的指针来调用。由于您没有新建对象,而是放置-新建对象,因此您不能调用delete

关于c++ - 通过一次调用 new 运算符来批量分配对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20524280/

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