用途:在C++中的预定位置构造对象
Use of : Construction of objects at predetermined location in C++
在C++中的预定位置构造对象有什么用?
以下代码说明了在预定位置的施工-
void *address = (void *) 0xBAADCAFE ;
MyClass *ptr = new (address) MyClass (/*arguments to constructor*/) ;
这最终会在预定的"地址"创建MyClass的对象。(假设地址指向的存储空间足够大,可以容纳MyClass对象)。
我想知道在内存中这样预先确定的位置创建对象的用途。
一个新放置很有用的场景是:
您可以预先分配一次大缓冲区,然后使用多个放置new
运算符
这会给你更好的性能(你不需要每次都重新分配)和更少的碎片内存(当你需要小内存块时)。这通常是std::vector
实现所使用的。
缺点是,您必须手动管理分配的内存。由放置new
分配的对象一旦不再需要,就需要显式析构函数调用。
考虑到为瓶颈分析您的应用程序始终是可取的,而不是跑到新的位置进行预优化。
主要有两种情况:
第一种情况是,例如在嵌入式系统中,必须在给定的已知位置构造对象。
第二种情况是,出于某种原因,您希望以默认以外的方式管理内存。
在C++中,像pA = new(...) A(...)
这样的表达式做两件连续的事情:
- 调用
void* operator new(size_t, ...)
函数,然后 - 调用CCD_ 6
由于调用new是调用A::A()的唯一方法,因此向new添加参数可以专门化不同的内存管理方式。最琐碎的是"使用通过其他方式获得的内存"。
当分配和施工需要分开时,这种方法很好。典型的情况是std::allocator
,其目的是为给定的数量分配未初始化的内存,而对象构造发生在稍后。
例如,在std::vector
中会发生这种情况,因为它必须分配一个通常比实际size
宽的capacity
,然后在已经存在的空间中构造对象作为push_back
。
事实上,默认的std::allocater实现,当asket分配n个对象时,会执行return reinterpret_cast<T*>(new char[n*sizeof(T)])
,因此分配空间,但实际上不构造任何内容。
承认std::vector存储:
T* pT; //the actual buffer
size_t sz; //the actual size
size_t cap; //the actual capacity
allocator<T> alloc;
push_back的实现可以是:
void vector<T>::push_back(const T& t)
{
if(sz==cap)
{
size_t ncap = cap + 1+ cap/2; //just something more than cap
T* npT = alloc.allocate(ncap);
for(size_t i=0; i<sz; ++i)
{
new(npT+i)T(pt[i]); //copy old values (may be move in C++11)
pt[i].~T(); // destroy old value, without deallocating
}
alloc.deallocate(pt,cap);
pT = npT;
cap = ncap;
// now we heve extra capacity
}
new(pT+sz)T(t); //copy the new value
++sz; //actual size grown
}
本质上,需要将分配(与整个缓冲区相关)与元素的构建(必须在现有缓冲区中进行)分开。
通常在嵌入式或驱动程序代码中使用预先确定的位置,其中一些硬件通过特定的地址范围进行寻址。
但在这种情况下,该地址的存储不用于访问,或者更好的是,它不是有意的(或者最好不必用于访问,因为你不知道新操作员正在使用它),因为稍后会执行新操作。
您使用它作为初始化值(new并没有真正更改它)。我想到了两个目的:首先,如果你后来忘记了一个新的,你会立即在调试器中看到你的魔法地址(即在本例中为0xBAAADCAFE)。
其次,您可以在摆弄新操作符并需要init值的情况下使用,这样您就可以调试它(例如,您可以看到更改)。
或者你已经修改了你的新操作符,它用这个神奇的数字做任何事情(例如,你可以用它进行调试,或者,像上面提到的那样,真正使用特定地址的内存用于某些硬件),在不同的分配方法之间切换。。。
EDIT:在这种情况下,要想回答正确,需要查看新操作员的实际操作,您应该检查新闻源代码。
当您通过将一个长的DWORD、DWORD_PTR或其他大小的指针作为参数传递给函数来知道类的地址,并且需要重建该类的副本以供O-O使用时,这种特殊行为非常有用。
或者,这也可以用于在预先分配的内存或您确定为静态的位置中创建类(即:您正在将应用程序与一些古老的ASM库链接)。
自定义分配器、实时(此处无锁)和性能。
- 将值指定给向量(2D)的向量中的某个位置
- 使用Unreal C++获取VR耳机的世界位置/方向
- 写入位置0x0000000C时发生访问冲突
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- GL_SHADERSTORAGE_BUFFER位置是否与其他着色器位置冲突
- 如何使用cudaMallocManaged在指针位置初始化对象?(C++)
- 无法获取webot::PositionSensor对象中位置传感器的值
- 非常量变量只读位置的赋值
- 如何定义更改car类中car位置的方法
- 使用迭代器时如何访问对象在向量中的位置?
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 求最大元素位置的分治算法
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 是与初始类同一内存位置的重新定位类
- 如何在使用网格布局时重叠qwidgets,并将重叠的widget定位在距离窗口边界特定距离的位置
- 我不知道如何定位最高随机数的位置
- 如何在MFC上设置窗口位置以将其定位到屏幕顶部
- 将QGraphicsSvgItem的中心定位在一个位置上。
- 如何定位WinRT异步方法调用中出现错误的位置
- 重定位表项在平面二进制文件中的存储位置