Reputation: 23
I am working on an application where I am allocating memory from a pool for use with arithmetic data types - all fundamentals, except for std::complex. I have been using malloc, ensuring alignment, and casting the pointer to the data type without any issues. I know placement new is, in general, required for doing this with objects. However, I am not clear if this is required for fundamental data types, and if there are any exceptions to needing this with objects. Specifically, is this legal to do with std::complex?
//Simple example just using malloc
Class AnyClass;
AnyClass *p = malloc(sizeof(AnyClass));
//We have memory allocated for the size of AnyClass, but no object at that memory. Construct an object a location p using placement new
AnyClass *o = new (p) AnyClass;
//Then o can be used. To cleanup:
o->~AnyClass();
free(p);
//In C, we can just do the following. Is this legal in C++ (with fundamental types)?
int *p = malloc(sizeof(int));
//Can just use p as a pointer to int now. Cleanup is just:
free(p);
//If the omitting a call to placement new is legal with fundamental data types in C++, are there ANY objects where this is legal? If so, what exactly are the requirements? Is this ok with std::complex?
Upvotes: 2
Views: 275
Reputation: 238321
Is placement new required when using allocated memory with fundamental data types?
Yes, placement new
is required in C++ to create objects into malloc
ated storage whether the type of the object is fundamental or not. Unless you create an object, you may not access it (except through a char*
or similar).
The destructor call is not necessary for trivially destructible types.
There is a proposal p0593r2 to introduce "Implicit creation of objects for low-level object manipulation" to the language, which would remove the need for placement new in this case. It was not adopted into C++20.
P.S. AnyClass *p = malloc(sizeof(AnyClass));
is ill-formed, since malloc
returns a void*
which is not implicitly convertible to AnyClass*
in C++.
for trivially copyable types, it is legal to allocate memory using malloc and do a memcpy.
Same as above. The copying is legal, but unless you create objects, you cannot access the memory that you copied.
static_assert(std::is_trivially_copyable_v<AnyClass>);
AnyClass a{};
void* p = malloc(sizeof(AnyClass)); // It is OK to allocate
Bad example:
std::memcpy(p, &a, sizeof a); // It is OK to copy memory
AnyClass* o = static_cast<AnyClass*>(p); // Still OK (but not useful)
int i = o->some_member; // NOT OK; no object exists
Good example:
AnyClass *o = new (p) AnyClass;
std::memcpy(p, &a, sizeof a);
//std::memcpy(o, &a, sizeof a); // or this; either works
int i = o->some_member; // OK; object exists
Upvotes: 1
Reputation: 2157
Not sure if I understand you correctly, but it seems like you don't need to allocate objects dynamically (from the memory pool aka heap).
You also don't need to use malloc but can use new with delete. This is better than malloc/free at least because new will automatically call a constructor and delete will call a destructor.
Upvotes: 0