如何在不使用 new 的情况下进行默认初始化
How to default-initialize without using new?
我正在尝试实现我自己的std::vector
容器,并且我正在使用realloc()
来调整它的大小,以防止每次都删除和重新分配。使用以下代码:
buffer = new T[n]();
这将默认初始化数组的每个元素,并允许我立即开始访问它们。但是,由于标准规定内存must be previously allocated by malloc(), calloc() or realloc()
使用realloc()
,因此我无法使用new
。
我知道calloc()
会将内存零初始化,但我不确定这是否会与new T[n]()
具有相同的行为。使用 C 样式内存分配进行默认初始化的正确方法是什么?
首先,不,零初始化内存与为该内存应该包含的对象调用默认构造函数不同。你必须调用构造函数。因此,就正确性而言,malloc
与calloc
并不重要;所以如果你要走那条路,用malloc
- 它更快。
其次,realloc
不会直接工作,因为它不知道如何复制对象。有些对象可以逐字节复制,对于这些类型,realloc
是可以的。但对于大多数类型,复制涉及其他操作,您必须使用 copy 构造函数或 copy 赋值运算符来执行复制。因此,realloc
可以在特殊情况下使用,但不能在一般情况下使用。
所以,你真的仅限于malloc
和free
,以及构造函数(通过放置new
(和析构函数。
您可以使用以下语法调用具有任何类型的内存的任何构造函数:
::new (ptr) T(...arguments go here (if any)...);
您可能需要使用
#include <new>
它将为在 ptr 分配的内存调用 T 的构造函数。对于数组,您必须循环:
T* ptr=(T*)malloc(sizeof(T)*n);
for(int i=0;i<n;++i)
::new(ptr+i) T();
但是有了这个,不要调用删除!您必须为每个项目显式调用析构函数,然后使用正确的函数释放内存:
for(int i=0;i<n;++i)
(ptr+i)->~T();
free(ptr);
在 realloc 的情况下,您必须确保 T 对象可以毫无问题地重新定位(字节到字节复制正常(。对于具有简单数据类型的结构,它应该是安全的。
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 是默认情况下分配给char数组常量的值
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- CMake:默认情况下,如何使add_custom_command输出保持最新?
- 在没有默认构造函数的情况下创建的派生对象
- 在 C++ 中,默认情况下构造函数为类的数据成员提供的值是多少?
- 如何防止类中的类对象尝试在没有默认构造函数的情况下自动构造自身?
- Vulkan默认情况下已经有多线程了吗
- 默认情况下,"std::shared_ptr"不应该使用"std::d efault_delete"吗?
- 为什么C++默认情况下不移动构造右值引用?
- 默认情况下初始化时 POD 是否给予特殊处理 (C++14)?
- 在不使用默认构造函数的情况下声明 POD 结构时,会实例化什么?
- 默认情况下,C++ 开关运行时循环
- 谷歌嘲笑!我的测试出错.默认情况下,呼叫将返回调用
- 如何将用户下载的标头文件添加到系统中默认情况下的标题文件列表
- 默认情况下C++数组作为参数引用
- 为什么默认情况下初始化局部变量
- 默认情况下,我如何在不使用继承的情况下使用所有构造函数
- 为什么我能够在没有默认构造函数的情况下默认构造对象