这里有人用过c++的“placement new”吗?如果有,为什么?在我看来,它只在内存映射硬件上有用。
当前回答
我还有一个想法(它对c++ 11有效)。
让我们看看下面的例子:
#include <cstddef>
#include <cstdio>
int main() {
struct alignas(0x1000) A {
char data[0x1000];
};
printf("max_align_t: %zu\n", alignof(max_align_t));
A a;
printf("a: %p\n", &a);
A *ptr = new A;
printf("ptr: %p\n", ptr);
delete ptr;
}
使用c++ 11标准,GCC给出以下输出:
max_align_t: 16
a: 0x7ffd45e6f000
ptr: 0x1fe3ec0
PTR没有正确对齐。
对于c++ 17标准和更高级的标准,GCC给出了以下输出:
max_align_t: 16
a: 0x7ffc924f6000
ptr: 0x9f6000
PTR对齐正确。
据我所知,c++标准在c++ 17之前不支持过对齐的new,如果你的结构的对齐大于max_align_t,你就会遇到问题。 要在c++ 11中绕过这个问题,可以使用aligned_alloc。
#include <cstddef>
#include <cstdlib>
#include <cstdio>
#include <new>
int main() {
struct alignas(0x1000) A {
char data[0x1000];
};
printf("max_align_t: %zu\n", alignof(max_align_t));
A a;
printf("a: %p\n", &a);
void *buf = aligned_alloc(alignof(A), sizeof(A));
if (buf == nullptr) {
printf("aligned_alloc() failed\n");
exit(1);
}
A *ptr = new(buf) A();
printf("ptr: %p\n", ptr);
ptr->~A();
free(ptr);
}
在这种情况下PTR是对齐的。
max_align_t: 16
a: 0x7ffe56b57000
ptr: 0x2416000
其他回答
我曾看到它被用作“动态类型”指针的轻微性能hack(在“引擎盖下”一节中):
但这是我用来获得小类型的快速性能的棘手技巧:如果所持有的值可以放入void*中,我实际上不需要分配一个新对象,而是使用placement new将其强制到指针本身。
它被std::vector<>使用,因为std::vector<>通常分配比vector<>中的对象更多的内存。
在http://xll.codeplex.com上查看xll项目中的fp.h文件,它解决了喜欢随身携带维度的数组“与编译器的不必要的亲密关系”问题。
typedef struct _FP
{
unsigned short int rows;
unsigned short int columns;
double array[1]; /* Actually, array[rows][columns] */
} FP;
The one place I've run across it is in containers which allocate a contiguous buffer and then fill it with objects as required. As mentioned, std::vector might do this, and I know some versions of MFC CArray and/or CList did this (because that's where I first ran across it). The buffer over-allocation method is a very useful optimization, and placement new is pretty much the only way to construct objects in that scenario. It is also used sometimes to construct objects in memory blocks allocated outside of your direct code.
我在类似的情况下使用过它,尽管它不经常出现。不过,它是c++工具箱中的一个有用工具。
如果你正在构建一个内核,它很有用——你把从磁盘或页表读取的内核代码放在哪里?你得知道该往哪里跳。
或者在其他非常罕见的情况下,比如当你有大量分配的空间,想要把几个结构放在彼此后面。它们可以这样打包,而不需要使用offset()操作符。不过,还有其他的技巧。
我也相信一些STL实现使用了新位置,比如std::vector。它们以这种方式为2^n个元素分配空间,而不需要总是realloc。
推荐文章
- c++11返回值优化或移动?
- Windows和Linux上的c++编译:ifdef开关
- c++中size_t和int的区别是什么?
- 在C和c++中静态变量存储在哪里?
- 为什么标准迭代器范围是[begin, end]而不是[begin, end]?
- c++双地址操作符?(& &)
- 函数标题中的箭头操作符(->)
- 如何在c++中初始化一个向量
- 返回类型为'?:'(三元条件运算符)
- 当分配vector时,它们使用的是堆上的内存还是堆栈上的内存?
- 互斥实例/教程?
- 如何添加一个'或'条件在#ifdef
- 纯虚函数的实现
- 检索Linux上单个进程的CPU使用情况和内存使用情况?
- 为什么在c++中声明enum时使用typedef ?