c++ - 为什么placement-new 调用标准的placement operator new 函数?
问题描述
一个placement-new
带有单个参数的表达式,该参数是一个指向预分配内存的指针,将T
在该内存中构造一个类型的对象。
为什么它调用标准placement-new
运算符void* operator new ( std::size_t count, void* ptr );
,因为后者什么都不做,只返回它的指针参数?
int x = 10;
int* p = new(&x) int{1024};
你能解释一下编译器在上面采取的步骤来构造一个新
int
的内存地址x
吗?为什么
placement-new
表达式不直接在它作为指针获得的内存地址处构造一个对象,而不是调用一个什么都不做并且只返回其指针参数的运算符函数?
解决方案
一般的规则是new (args...) T
会调用operator new(sizeof(T), args...)
,并且这个函数需要返回void*
。如果此operator new
调用成功返回,则将对象构造到返回值指向的内存中。
这个通用规则足够强大,可以同时支持普通的 new 表达式new int
和放置形式new (&x) int
,而无需任何特殊情况。这两个表达式调用不同的重载operator new
,这就是为什么前者分配而后者不分配的原因。无论如何,最后都会构造一个对象(除非operator new
函数因抛出异常而失败)。
无需在语言中设置特殊规则,即表示operator new
不被放置新表达式调用。相反,编译器可以通过直接构造int
对象来简单地优化代码,&x
而无需先调用operator new
,因为它已经知道放置operator new
只会返回其第二个参数。
(其实实际情况比这复杂一点。如果T
是数组类型,则operator new[]
调用 then 而不是operator new
,编译器可能会请求operator new[]
比数组实际占用更多的内存,并在构造之前调整返回的指针数组。还有一些与过度对齐类型有关的特殊规则,实际上还有一些用于放置 new 和 delete 的特殊情况。这些细节与这个答案无关。)
推荐阅读
- mysql - 使用 DML 语句作为一个整体而不是部分地操作数据库中的数据
- coldfusion - 如何使用coldfusion获取雅虎天气信息
- expo - 是否可以通过 Expo 将 web url 转换为应用程序
- python - 使用 BeautifulSoup 在预标记中抓取文本
- tensorflow - Tensorflow warning: two cells provided to MultiRNNCell are the same object
- image - How to always show inline images?
- html - 仅使用 css 将 div 增加到一个方向
- r - how to count the number of event on one data.frame based on time period on another data.frame
- c# - 使用用户名和密码连接 gmail api
- java - 带有 MPAndroidChart 和图像的图形饼图