I have a buffer in C with this code
buffer = malloc(sizeof(uint32_t)*CACHE_LEN*2);
How can I change this line to C++?
Is it better with
malloc or with
I cannot understand the meaning of this
The line you mention will compile fine in C++, save for that fact that if
buffer is not a
void *, then you may need to cast the return value of
malloc in C++, which you don't need to do in C (and probably should not do).
uint32_t *buffer = (uint32_t *) malloc(sizeof(uint32_t)*CACHE_LEN*2);
However, you may wish to convert to a
delete paradigm; that will require more than just changing that line.
uint32_t *buffer = new uint32_t[CACHE_LEN*2]; ... delete buffer;
If you want to be more C++-like still, then use
std::vector or similar:
CACHE_LEN is indeed a macro that hides a value that is known at compile time:
auto buffer = make_unique<array<uint32_t, CACHE_LEN*2>>();
This has the fun property that you get pretty much all the advantages of modern C++ at just about zero overhead.
If you wish to stay somewhat closer to your C roots or
CACHE_LEN is not known at compile time, you can alternatively use, which removes some features that
auto buffer = make_unique<uint32_t>(CACHE_LEN*2);
Finally, if you want to go all the other way, you can use a fully dynamic array (
vector in C++ lingo):
auto buffer = std::vector<uint32_t>(CACHE_LEN*2);
All of the above solutions ensure that resource management is being done by the scope of
buffer. The solutions that use
make_unique can (more or less) easily be changed to use shared pointers instead.
To stay completely old-school,
std::free exist in C++ as well, but
malloc requires casting its result to the proper pointer type. They can also be replaced with
new uint32_t[CACHE_LEN*2] and
The meaning of the
sizeof(uint32_t) is simply to account for the fact that
malloc does not allocate a number of elements, but rather a number of bytes - and most types require more than 1 byte per element.
std::vector<uint32_t> v(CACHE_LEN * 2);
sizeof(type) return the size in chars of the type of the expression passed. For a
uint32_t it would be 4.
sizeof() gives the size in byte of the type given between the parenthesis. The type takes sizeof() in memory. This you need to know when you allocate memory to store data in. The
CACHE_LEN * 2 depends solely on your usage.
If you need to store five times a pair of uint32_t you use:
malloc( sizeof( uint32_t ) * 2 * 5 );
malloc will allocate a fixed size of memory. This means you can't change the size.
The new/delete is equivalent to malloc/free but in C++. If you use new you should use delete also.
char buf = new char[ 10 ]; delete buf;
The delete goes where the life cycle of the allocated memory has ended. If you create it within a function, then the delete should be there too. Or you get memory leaks. If you have it at the global scope of a class and you allocate the memory in the constructor, it is an assumption to delete the memory in the destructor but is usually the case. It depends on why and when you need the memory. One thing is for sure, if you allocate you need to deallocate (new/delete).<blockquote>
Paolo Bolzoni mentioned the use of std::vector</blockquote>
That's perfectly fine and in most cases very easy to use. If you need to optimize your code for speed, having a fixed size memory block would be faster then a std::vector. It depends on your needs but also your preference.Answer5:
buffer = malloc(sizeof(uint32_t)*CACHE_LEN*2);
This can be <em>"translated"</em> in C++ in several ways.
But, first it must be clear what this does in C, since you wrote in your question that it's not clear for you the meaning of
malloc(), you can dynamically (i.e. at <em>run-time</em>) allocate some <strong>contiguous</strong> space from the <em>heap</em>.<br />
The parameter you pass to
malloc is the <em>size</em> of the requested space, <strong>in bytes</strong>.<br />
The code you posted seems to allocate
CACHE_LEN*2 count of
uint32_t elements. Since
malloc expects its size parameter to be measured <em>in bytes</em>, you have to multiply
CACHE_LEN*2 (the <em>"count"</em> factor) by the size, in bytes, of each element, i.e. of a
uint32_t, which is
So, you have:<ul><li>element type:
uint32_t</li> <li>element count:
CACHE_LEN*2</li> <li>size of each element, in bytes:
<em>Total size in bytes</em> for
sizeof(uint32_t) * CACHE_LEN*2
Now that this
malloc() call should be clear, let's move forward to the C++ equivalent.
The most immediate "mapping" is from C's
malloc() to C++'s <strong>
Note that, while
malloc requires the size to be expressed in <em>bytes</em>, when you call
new you can just specify the <strong>element count</strong> (<em>not</em> the <em>raw</em> byte count).
So, a C++ code using
new would be something like this:
// Allocate (CACHE_LEN*2) elements of type uint32_t uint32_t* buffer = new uint32_t[CACHE_LEN*2];
When you allocate memory using
malloc(), you have to free it using
The C++ counterpart of
new is <strong>
// Release buffer memory allocated with new delete buffer; // Avoid dangling references buffer = nullptr;
But there's more. When <strong>memory allocation fails</strong>,
malloc just returns
NULL. Instead, C++'s
new <strong>throws an exception</strong> in case of allocation failure. This exception is of type
std::bad_alloc. You can catch that somewhare in your code to handle the memory allocation failure case.
If you want a behavior similar to
malloc, with failed allocations returning a
nullptr pointer, you can use the <strong>
std::nothrow</strong> constant with
buffer = new (std::nothrow) uint32_t[CACHE_LEN*2]; // On allocation failure, just returns nullptr // (does *not* throw an exception).<hr />
However, in <em>modern C++</em> code, you may want to use a convenient container class to store your contiguous buffer memory. A very common candidate for that is <strong>
std::vector is a class template: you specify the type of the elements as template argument, and you can specify the element count as a constructor parameter, e.g.:
#include <vector> // For std::vector .... std::vector<uint32_t> buffer(CACHE_LEN*2);
Since the default memory allocator for
new for allocating memory, in case of allocation failure the above constructor will throw a
std::bad_alloc C++ exception.
Note that the memory allocated by a
vector is <strong>automatically</strong> released by the vector's <em>destructor</em>. So you don't have to manually release that memory. This helps writing code that is <em>structurally incapable of leaking memory</em> (and other resources).
You can access the items in the vector using its overloaded
operator, just like an ordinary simple raw array (e.g.
buffer[i] accesses the i-th item in the buffer; note that indexes are
If you want a pointer to the beginning of the vector (which is the strict equivalent of your
buffer pointer), you can call
vector's <strong>data()</strong> method, e.g.:
// Points to the beginning of vector memory uint32_t* ptr = buffer.data(); // ...use ptr...Answer6: