#include <iostream>
using namespace std;
int main()
{
char* MainBlock = new char[100];
char* SubBlock1 = new (MainBlock) char[20];
char* SubBlock2 = new (MainBlock) char [20];
cout << static_cast<void*>(SubBlock1) << " " << static_cast<void*>(SubBlock2);
}
为什么上面代码中的两个指针都有相同的地址?我希望SubBlock2在SubBlock 1之后是20个字节。
这是否意味着即使我只有100个字节,我可以分配无限数量的指针与新的位置?
如何使用placement new确保SubBlock6是nullptr还是越界?
为什么上面代码中的两个指针都有相同的地址?
Placement new接受初始化正在创建的对象的确切地址。您传递相同的地址,您获得相同的地址。
这是否意味着即使我只有100个字节,我可以分配无限数量的指针与新的位置?
不会。每个展示位置重新使用存储空间。您当然可以无限次地重复使用存储,但您最多只能分配相同的100个字符。
如何使用placement new确保SubBlock6是nullptr还是越界?
不可能。一开始就是为您提供有效的存储空间以便创建对象。如果不这样做,则行为未定义。
最后,您不需要放置新的放置。
char *SubBlock1 = MainBlock;
char *SubBlock2 = MainBlock + 20;
将缓冲区分区就好了。只要确保delete[]
只存储在MainBlock
中的指针值。
(MainBlock)
参数是一个放置参数。事实上,你明确告诉程序在SubBlock1
的地址分配SubBlock2
和MainBlock
。
每个new
expression获取构造对象的地址调用适当的allocation function。一旦完成分配并从分配函数返回地址,它就会尝试在指定的地址处精确构造对象。
鉴于char* SubBlock1 = new (MainBlock) char[20];
,它调用以下分配函数:
void* operator new[]( std::size_t count, void* ptr );
由标准数组表单放置新表达式调用。标准库实现不执行任何操作并返回未修改的ptr。
如上面的文档所述,调用此分配函数不执行任何操作并返回未经修改的地址。所以,这个新的表达式恰好在char
构建了20个MainBlock
。这就是为什么你得到SubBlock1
和SubBlock2
相同的地址。
这是否意味着即使我只有100个字节,我可以分配无限数量的指针与新的位置?
不。请注意,分配和构造是两回事。在您的示例中,您只分配一次内存并在其上多次构造对象。因此,在分配的内存上构建的对象的布局由您决定。