使用新位置处理内存

Handling memory using placement new

本文关键字:处理 内存 位置 新位置      更新时间:2023-10-16

我正在练习新的实习。起初,我认为placement new会自动管理内存,不会使变量重叠,但我认为事实并非如此(请纠正我并强调这一点)。下面的代码似乎在相同的地址位置分配了新的变量。

int arr[2] = {};
cout<<arr<<endl;
for(int i = 0; i<2;i++)
{
    int *x = new(arr) int(i);
    cout<<*x<<" "<<x<<endl;
} 

将其更正为以下代码似乎可以解决问题(有什么建议吗?它正确吗?)

int arr[2] = {};
cout<<arr<<endl;
for(int i = 0; i<2;i++)
{
    int *x = new(arr+i) int(i);
    cout<<*x<<" "<<x<<endl;
}

此外,还有一个疑问,我需要澄清。上面的做法好吗(可能不是因为它可能会在更改循环条件时溢出容器)或放置新容器时只应一次性用于分配变量。

如果我想在一个容器中分配变量,而不是一次性分配,并检查边界泄漏,那么使用placement new分配变量的任何更好的方法。

您自己已经回答了这个问题,基本上,当您想要创建一个对象并告诉它应该使用哪个内存地址时,将使用placement new。

放置new的一个典型用途是在共享内存上创建一个对象

发件人:http://www.drdobbs.com/creating-stl-containers-in-shared-memory/184401639

共享内存中的C++STL容器想象一下,将STL容器(如映射、向量、列表等)放置在共享内存中。将这种强大的通用数据结构放置在共享内存中,为使用IPC共享内存的进程配备了一个强大的工具。无需为通过共享存储器进行通信而设计和开发特殊的数据结构。此外,STL的全部灵活性可以用作IPC机制。STL容器在盖子下面管理自己的内存。将项目插入STL列表时,列表容器会自动为内部数据结构分配内存,以容纳插入的项目。考虑在共享内存中放置一个STL容器。容器本身分配其内部数据结构。在堆上构造STL容器,将容器复制到共享内存中,并确保容器的所有内部内存都指向共享内存区域,这是一项不可能完成的任务。

过程A执行以下操作:

//Attach to shared memory
void* rp = (void*)shmat(shmId,NULL,0);
//Construct the vector in shared
//memory using placement new
vector<int>* vpInA = new(rp) vector<int>*;
//The vector is allocating internal data
//from the heap in process A's address
//space to hold the integer value
(*vpInA)[0] = 22;
Process B does the following:
vector<int>* vpInB =
  (vector<int>*) shmat(shmId,NULL,0);
//problem - the vector contains internal 
//pointers allocated in process A's address 
//space and are invalid here 
int i = *(vpInB)[0];

Placement new对于编写异常安全代码和减少对类型的要求也非常有用,因为您可以将内存分配与对象构造分开。

例如,

new T[size]

分配内存,默认构造大小为T类型的对象。

operator new(sizeof(T) * size)

然而,操作符new只分配内存,不需要类型T的默认构造。然后,您可以使用placement new在分配的内存中构造对象。这很有用,因为有很多类不提供默认构造,而在第一个示例中无法使用默认构造。

请注意,当使用placementnew时,应该显式调用要销毁的任何对象的析构函数,而不是调用delete。此外,如果您使用operator new来分配内存,则应使用operator delete来释放内存。例如

auto pBlock = operator new(sizeof(T)); // allocate memory for T   
new (pBlock) T(value); // construct T in place
auto pT = static_cast<T*>(pBlock); // convert the pointer to something useful
pT->~T(); // destruct T
operator delete(pBlock); // free memory

整个放置点都是为了完全绕过C++的内存管理。"普通"new将分配必要的内存,然后对其进行初始化。Placement new将初始化您指定的地址,并假设可以覆盖该内存。您几乎从不需要更换新的!

您可能想要使用replacement new的典型场景是与不在应用程序控制范围内的内存进行交互。这种情况有时发生在嵌入式系统或其他低级编程任务中。