- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试为 C++ 实现一个自定义分配器,它适用于任何形式的 new/delete/malloc/free。
我的程序是如何工作的,我在程序开始时分配了一个x 字节的内存池并使用它们。例如,当有人写 int* a= new int;
时,我的程序将从可用的内存池中返回地址并将其标记为已分配,并且该地址连同分配的大小从内存池。当有人写delete a;
时,地址返回到内存池中,可以再次使用。
我的问题是我不完全理解如何new(placement)
有效,我应该如何处理它,因为当我的函数被调用以在 new/malloc 上分配内存时,我只有程序需要的内存大小作为参数我只是返回一个可用地址到要使用的内存。考虑以下示例
auto p = (std::string*)malloc(5 * sizeof(std::string));
void * placement = p;
new(placement) std::string(4, (char)('a'));
std::cout<< *p;
在第一行,我的自定义分配将从我的内存池中向 p 返回一个地址,其中可用内存总数为 5* sizeof(std::string))
,在第三行行我的自定义分配器将再次分配内存返回另一个地址。当我打印 *p
时,它打印的正是我所期望的 aaaa
。
它应该这样工作吗?
最佳答案
一个普通的 new
做两件事:
分配存储;和
构造一个对象。
现在我们要把这两个步骤分开。分配原始存储空间很容易,但是在 C++ 中没有在给定地址构造对象的“ native ”方法。因此,new
运算符被重载以实现此目的,通过返回第一步的给定指针。
我们不需要相应的delete
,因为我们可以手动调用析构函数。在 C++17 中,std::destroy_at
被添加到标准库中。自 C++20 起,std::construct_at
可用于构造对象而不是放置 new:
std::construct_at(p, 4, 'a');
C++ Super-FAQ很好地解释了 placement new:
There are many uses of placement new. The simplest use is to place an object at a particular location in memory. This is done by supplying the place as a pointer parameter to the new part of a new expression:
#include <new> // Must #include this to use "placement new"
#include "Fred.h" // Declaration of class Fred
void someCode()
{
char memory[sizeof(Fred)]; // Line #1
void* place = memory; // Line #2
Fred* f = new(place) Fred(); // Line #3 (see "DANGER" below)
// The pointers f and place will be equal
// ...
}Line #1 creates an array of
sizeof(Fred)
bytes of memory, which is big enough to hold aFred
object. Line #2 creates a pointerplace
that points to the first byte of this memory (experienced C programmers will note that this step was unnecessary; it’s there only to make the code more obvious). Line #3 essentially just calls the constructorFred::Fred()
. Thethis
pointer in theFred
constructor will be equal toplace
. The returned pointerf
will therefore be equal toplace
.ADVICE: Don’t use this “placement new” syntax unless you have to. Use it only when you really care that an object is placed at a particular location in memory. For example, when your hardware has a memory-mapped I/O timer device, and you want to place a
Clock
object at that memory location.DANGER: You are taking sole responsibility that the pointer you pass to the “placement new” operator points to a region of memory that is big enough and is properly aligned for the object type that you’re creating. Neither the compiler nor the run-time system make any attempt to check whether you did this right. If your
Fred
class needs to be aligned on a 4 byte boundary but you supplied a location that isn’t properly aligned, you can have a serious disaster on your hands (if you don’t know what “alignment” means, please don’t use the placement new syntax). You have been warned.You are also solely responsible for destructing the placed object. This is done by explicitly calling the destructor:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
// ...
f->~Fred(); // Explicitly call the destructor for the placed object
}This is about the only time you ever explicitly call a destructor.
关于c++ - 自定义分配器,包括放置新案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58900136/
我有一个 map我需要插入和删除 Foo * 的地方.用法看起来像 map mapping; while( a long time) { // make ne
我想知道这是做什么的: std::basic_string, std::allocator>:: basic_string, std::allocator> (&myText, "hello worl
是否可以在 C++ 中创建一个像这样简单工作的自定义分配器: { // Limit memory to 1024 KB ScopedMemoryPool memoryPool(1024
我正在使用提到的 STL 分配器 here . 我所做的唯一更改是我从一个名为 Object 的基类继承,并且我使用基类的 new 和 delete 函数进行分配。 class MyAlloc
我有一段代码可以创建数千个对象,并将它们附加到一个 vector 中。下面的代码只是一个正在做的事情的例子,尽管构造函数有一些参数,而for实际上并没有那个条件,但它起到了表明它运行了数千次的目的。
这里有两个问题。首先,如果我需要在 Clone 之前创建 b2BlockAllocator 然后在克隆之后删除(在哪里?)? Xcode 分析工具未显示 C++ 泄漏... b2FixtureDef
我想创建一个不可复制的分配器(在 C++14 中),它只分配一个 std::vector 可以使用的固定内存块。我想防止分配器(以及 vector )被复制,以防止用户意外分配内存。分配器仅用于 st
我在 http://msdn.microsoft.com/en-us/library/ee292117.aspx 上看到和 http://msdn.microsoft.com/en-us/librar
我想用更健壮的分配器替换标准分配器(C++ 标准只需要对 vector::resize 进行溢出检查)。许多库提供的各种 C++ 分配器在进行负面 self 测试时会一败涂地。 我可以使用更强大的分配
我的 STL 容器中的内存使用预计是不稳定的——也就是说它会经常收缩和增长。我正在考虑通过为 STL 容器类型声明指定一个分配器来解决这个问题。我知道矿池分配器旨在处理这种情况,但我担心的是波动性将超
我有一个大量使用 STL 容器和字符串的大型(>250 个文件)库的源代码。我需要在有限堆的嵌入式环境中运行它,所以我想确保这个库本身的堆使用受到限制。 显而易见的解决方案是创建一个分配器,但修改整个
我想知道有一个符合 C++ 标准的库是否可行 allocator使用位于堆栈中的(固定大小的)缓冲区。 不知何故,这个问题似乎还没有在 SO 上这样问过,尽管它可能已经在其他地方得到了隐含的回答。 所
我观察到我的 MSVC10 副本附带的容器似乎允许基于状态的分配器,并编写了一个简单的池分配器,为特定类型分配池。 然而,我发现如果_ITERATOR_DEBUG_LEVEL != 0 MSVC 向量
据我所知,当 vector 空间不足时,分配器用于创建新空间。但是,我想创建一个自定义调整大小策略,该策略将移除底部 25% 的元素并始终保持相同的大小。这是为了构建一个空间有限的缓存。 有没有我可以
我目前正在尝试使用 Microsoft Visual Studio 2012 编译一个相当大的项目。我发现它在旧版本上编译得很好,但是对于这个版本,我在 std::list 的任何地方都会出错仅与一个
因此,在所提供代码的下一行,我有 IntelliSense 警告:“没有可用的成员”。怎么了?在正常情况下,似乎有选项,如“分配”、“解除分配”等。 namespace MyLib { tem
我正在尝试在 Microsoft visual studio 2013 on C++ 上编译为 linux 编写的程序。 声明 sdesc_t *ret = _malloc(sizeof(sdesc_
由于我工作的政策,我无法使用高于 1.33.1 的 Boost 版本,也无法使用高于 4.1.2 的 GCC 版本。是的,这是垃圾,但我对此无能为力。 Boost 1.33.1 不包含进程间库。 也就
我正在为 T 类型的数组实现资源分配克隆操作。直接的实现使用 new T[sz],然后是从源到新数组的 std::copy 调用。它遍历内存两次。 我想分配原始内存然后使用 std::uninitia
我们有一个库,它通过 extern "C" 提供 C 接口(interface),并从 C 代码中使用,但为了方便起见,它内部使用了 STL 容器和一些 C++ 功能,如 RAII。 现在有一个新的要
我是一名优秀的程序员,十分优秀!