C++ 定位 new

C++ 定位 new

定位 new(placement new) 是 C++ 中的一种特殊的 new 运算符,用于在指定的内存地址上构造对象。它允许开发者在预先分配的内存区域中构造对象,而不是从堆中分配新的内存。这在需要精确控制内存布局或在预先分配的内存中构造对象的场景中非常有用。

主要功能

  • 在指定内存地址上构造对象:定位 new 允许在预先分配的内存区域中构造对象。
  • 避免额外的内存分配:通过在已有的内存区域中构造对象,可以避免额外的内存分配开销。
  • 精确控制内存布局:适用于需要精确控制对象在内存中布局的场景。

语法

定位 new 的语法如下:

1
new (address) Type(arguments);
  • address:指定的内存地址,通常是一个 void* 指针。
  • Type:要构造的对象的类型。
  • arguments:构造函数的参数列表。

示例

以下是一些使用定位 new 的示例,展示了如何在指定的内存地址上构造对象。

示例 1:基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <new> // for placement new

class MyClass {
public:
MyClass(int value) : value_(value) {
std::cout << "MyClass constructor: " << value_ << std::endl;
}
~MyClass() {
std::cout << "MyClass destructor: " << value_ << std::endl;
}
void display() const {
std::cout << "Value: " << value_ << std::endl;
}

private:
int value_;
};

int main() {
// 分配足够的内存来存储一个 MyClass 对象
void* memory = operator new(sizeof(MyClass));

// 在指定的内存地址上构造 MyClass 对象
MyClass* obj = new (memory) MyClass(42);

// 使用对象
obj->display();

// 手动调用析构函数
obj->~MyClass();

// 释放内存
operator delete(memory);

return 0;
}

示例 2:在数组中使用定位 new

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <new> // for placement new

class MyClass {
public:
MyClass(int value) : value_(value) {
std::cout << "MyClass constructor: " << value_ << std::endl;
}
~MyClass() {
std::cout << "MyClass destructor: " << value_ << std::endl;
}
void display() const {
std::cout << "Value: " << value_ << std::endl;
}

private:
int value_;
};

int main() {
const int arraySize = 3;

// 分配足够的内存来存储一个 MyClass 对象数组
void* memory = operator new[](arraySize * sizeof(MyClass));

// 在指定的内存地址上构造 MyClass 对象数组
MyClass* objArray = static_cast<MyClass*>(memory);
for (int i = 0; i < arraySize; ++i) {
new (&objArray[i]) MyClass(i * 10);
}

// 使用对象数组
for (int i = 0; i < arraySize; ++i) {
objArray[i].display();
}

// 手动调用析构函数
for (int i = 0; i < arraySize; ++i) {
objArray[i].~MyClass();
}

// 释放内存
operator delete[](memory);

return 0;
}

注意事项

  1. 手动管理内存:使用定位 new 时,内存的分配和释放需要手动管理。需要确保在对象的生命周期结束时正确调用析构函数,并释放内存。
  2. 异常安全性:如果构造函数抛出异常,需要确保已构造的对象正确析构,并释放内存。
  3. 对齐要求:确保分配的内存满足对象的对齐要求。可以使用 std::align 函数来调整内存对齐。

总结

  • **定位 new**:用于在指定的内存地址上构造对象,允许在预先分配的内存中构造对象。
  • 语法new (address) Type(arguments);
  • 手动管理内存:需要手动管理内存的分配和释放,以及对象的构造和析构。
  • 应用场景:适用于需要精确控制内存布局或在预先分配的内存中构造对象的场景。

C++ 定位 new
https://linhanmic.github.io/2024/09/05/C++ 定位new/
作者
Linhanmic
发布于
2024年9月5日
更新于
2024年9月13日
许可协议