考虑以下代码片段就地构建POD(普通旧数据)结构的实例:
#include <new>
#include <cassert>
#include <cstddef>
struct Test
{
int a;
char b;
double c;
};
int main()
{
const std::size_t minimumNumberOfBytes = sizeof( Test ) * 4;
// Get a block of memory that can accommodate a Test instance and then some!
void* const ptrToMemBlock = new char[ minimumNumberOfBytes ];
assert( ptrToMemBlock );
// Construct a Test instance in-place.
const Test* const testInstance( ::new ( ptrToMemBlock ) Test() );
// Is this assumption guaranteed to be true?
assert( testInstance == ptrToMemBlock );
}
Run Code Online (Sandbox Code Playgroud)
最终断言()所代表的假设是否保证始终是正确的?或者可以想象编译器可能决定构建Test实例,比如在我在placement-new调用中指定的内存块开始之后的几个字节?
请注意,我在这里具体询问POD类型.我知道,如果涉及多个继承和类似的东西,事情就会变得越来越多.
Fre*_*pin 12
此断言将始终保持,因为new
需要以MAXIMUM可能的对齐方式返回内存块.BTW - 你的第一个assert()
没有价值,正常new
情况下不会返回nullptr
- 它会抛出或中止,只有"nothrow new
"才能返回nullptr
.
是的,断言将成立.new
创建单个对象的任何表达式都必须sizeof(Test)
从分配函数中请求确切的存储字节; 所以它必须将对象放在该存储的开头,以便有足够的空间.
注意:这是基于C++ 11中新表达式的规范.看起来C++ 14会改变措辞,所以未来答案可能会有所不同.
是的,最后一个assert
保证保持,因为这种形式的placement-new必须始终返回传递的指针,而不是为自己使用任何空间:
5.3.4新的
[expr.new]
8 new-expression可以通过调用分配函数来获取对象的存储空间(3.7.4.1).[...]
10允许实现省略对可替换全局分配函数的调用(18.6.1.1,18.6.1.2).当它这样做时,存储由实现提供,或者通过扩展另一个新表达式的分配来提供.[...]
11当new-expression调用分配函数并且该分配尚未扩展时,newexpression将请求的空间量作为类型的第一个参数传递给分配函数std::size_t
.该参数不得小于正在创建的对象的大小; 仅当对象是数组时,它可能大于正在创建的对象的大小.
[...]
你的new-expression调用全局placement-new分配函数.
这是不可替换的功能,因此不能扩展或省略分配.
此外,您不是分配数组而是分配单个对象,因此根本不会发生请求填充.
18.6.1.3安置表格
[new.delete.placement]
1这些函数是保留的,C++程序可能无法定义用于替换标准C++库(17.6.4)中的版本的函数.的(3.7.4)的规定并不适用于这些保留的安置形式
operator new
和operator delete
.Run Code Online (Sandbox Code Playgroud)void* operator new(std::size_t size, void* ptr) noexcept;
2返回:
ptr
.
3备注:故意不执行任何其他操作.
这保证了allocation-function返回传递的指针不变.
归档时间: |
|
查看次数: |
2378 次 |
最近记录: |