>我在 C 中有一个带有此代码的缓冲区
buffer = malloc(sizeof(uint32_t)*CACHE_LEN*2);
如何将此行更改为C++?
malloc
好还是new[]
好?
我无法理解这个sizeof(uint32_t)
的含义.
你提到的那行在C++中编译得很好,除了如果buffer
不是void *
,那么你可能需要在C++中强制转换malloc
的返回值,这在 C 中不需要(可能不应该这样做)。
例如:
uint32_t *buffer = (uint32_t *) malloc(sizeof(uint32_t)*CACHE_LEN*2);
但是,您可能希望转换为new
/delete
范式;这需要的不仅仅是改变这条线。
例如:
uint32_t *buffer = new uint32_t[CACHE_LEN*2];
...
delete[] buffer;
如果你想更像C++,那就使用std::vector
或类似的东西:
std::vector<uint32_t> buffer(CACHE_LEN*2);
假设CACHE_LEN
确实是一个宏,它隐藏了编译时已知的值:
auto buffer = make_unique<array<uint32_t, CACHE_LEN*2>>();
这有一个有趣的特性,您可以在几乎零开销的情况下获得现代C++的几乎所有优势。
如果您希望更接近您的 C 根目录,或者在编译时不知道CACHE_LEN
,则可以使用,这会删除array
提供的一些功能:
auto buffer = make_unique<uint32_t[]>(CACHE_LEN*2);
最后,如果你想走另一条路,你可以使用一个完全动态的数组(vector
C++术语):
auto buffer = std::vector<uint32_t>(CACHE_LEN*2);
上述所有解决方案都确保资源管理按buffer
范围完成。使用make_unique
的解决方案可以很容易地(或多或少)更改为使用共享指针。
为了保持完全老派,std::malloc
和std::free
也存在于C++中,但malloc
需要将其结果转换为正确的指针类型。它们也可以替换为 new uint32_t[CACHE_LEN*2]
和 delete[] buffer
.
附言:sizeof(uint32_t)
的含义只是为了解释这样一个事实,即malloc
不分配多个元素,而是分配多个字节 - 并且大多数类型需要每个元素超过 1 个字节。
std::vector<uint32_t> v(CACHE_LEN * 2);
sizeof(type)
返回传递的表达式类型的大小(以字符为单位)。对于uint32_t
,它将是4。
sizeof() 给出了括号之间给定类型的字节大小。该类型在内存中占用 sizeof()。当您分配内存以存储数据时,您需要知道这一点。CACHE_LEN * 2
完全取决于您的使用情况。
如果您需要存储五次一对uint32_t,请使用:
malloc( sizeof( uint32_t ) * 2 * 5 );
malloc
将分配固定大小的内存。这意味着您无法更改大小。
new/delete 等同于 malloc/free,但C++。如果你使用new[],你也应该使用delete[]。
char buf = new char[ 10 ];
delete[] buf;
delete[] 位于已分配内存的生命周期结束的位置。如果你在函数中创建它,那么 delete[] 也应该在那里。或者你会得到内存泄漏。如果将其放在类的全局范围内,并且在构造函数中分配内存,则假设删除析构函数中的内存[],但通常是这种情况。这取决于为什么以及何时需要内存。有一件事是肯定的,如果你分配,你需要释放(new[]/delete[])。
Paolo Bolzoni 提到了 std::vector 的使用
这很好,在大多数情况下非常易于使用。如果您需要优化代码以提高速度,那么拥有固定大小的内存块会比 std::vector 更快。这取决于您的需求,也取决于您的喜好。
buffer = malloc(sizeof(uint32_t)*CACHE_LEN*2);
这可以通过多种方式C++"翻译"。
但是,首先必须清楚这在 C 中的作用,因为您在问题中写道,您不清楚sizeof(uint32_t)
的含义。
使用 malloc()
,您可以动态(即在运行时)从堆中分配一些连续的空间。
传递给malloc
的参数是请求的空间的大小(以字节为单位)。
您发布的代码似乎分配了CACHE_LEN*2
uint32_t
元素的数量。由于malloc
期望其大小参数以字节为单位,因此您必须将CACHE_LEN*2
("count"因子)乘以每个元素的大小(以字节为单位),即sizeof(uint32_t)
uint32_t
的大小。
因此,您有:
- 元素类型:
uint32_t
- 元素数:
CACHE_LEN*2
- 每个元素的大小(以字节为单位):
sizeof(uint32_t)
所以:
malloc()
=sizeof(uint32_t) * CACHE_LEN*2
的总大小(以字节为单位)
现在这个malloc()
调用应该很清楚,让我们继续讨论C++等效项。
最直接的"映射"是从C的malloc()
到C++的new[]
。
请注意,虽然malloc
要求大小以字节表示,但当您调用new[]
时,您可以只指定元素计数(而不是原始字节计数)。
因此,使用 new[]
的C++代码将是这样的:
// Allocate (CACHE_LEN*2) elements of type uint32_t
uint32_t* buffer = new uint32_t[CACHE_LEN*2];
当您使用 malloc()
分配内存时,您必须使用 free()
释放它。new[]
的C++对应物是delete[]
,例如:
// Release buffer memory allocated with new[]
delete[] buffer;
// Avoid dangling references
buffer = nullptr;
但还有更多。当内存分配失败时,malloc
只返回NULL
。相反,C++ 的 new[]
会在分配失败时引发异常。此例外的类型为 std::bad_alloc
。您可以在代码中捕获某些内容以处理内存分配失败的情况。
如果你想要一个类似于malloc
的行为,失败的分配返回一个nullptr
指针,你可以将std::nothrow
常量与new[]
一起使用,例如:
buffer = new (std::nothrow) uint32_t[CACHE_LEN*2];
// On allocation failure, just returns nullptr
// (does *not* throw an exception).
但是,在新式C++代码中,您可能希望使用方便的容器类来存储连续的缓冲区内存。一个非常常见的候选人是 std::vector
.
std::vector
是一个类模板:将元素的类型指定为模板参数,并且可以将元素计数指定为构造函数参数,例如:
#include <vector> // For std::vector
....
std::vector<uint32_t> buffer(CACHE_LEN*2);
由于 vector
的默认内存分配器使用 new[]
来分配内存,因此在分配失败的情况下,上述构造函数将引发std::bad_alloc
C++异常。
请注意,vector
分配的内存由向量的析构函数自动释放。因此,您不必手动释放该内存。这有助于编写结构上无法泄漏内存(和其他资源)的代码。
您可以使用其重载operator[]
访问向量中的项目,就像普通的简单原始数组一样(例如 buffer[i]
访问缓冲区中的第 i 项;请注意,索引是0
基于 -的)。
如果你想要一个指向向量开头的指针(严格等价于你的buffer
指针),你可以调用vector
的data()方法,例如:
// Points to the beginning of vector memory
uint32_t* ptr = buffer.data();
// ...use ptr...
随着C++
,malloc
变得new
/new[]
,free
变成delete
/delete[]
。