I have a #define to my new macro, to use my own allocator, such as MYNEW(Type, Allocator) where I will go and allocate some raw memory using malloc, then later use placement new to allocate the type on the raw memory such as
#define MYNEW(Type, Allocator) Allocator->Alloc<Type>(sizeof(Type));`
template<typename Type>
Type* Alloc(unsigned int size) // Allocator::Alloc<Type>
{
return (Type*)new(malloc(reportedSize)) Type;
}
However, I am running into issues when there is no default constructor for Type. One scenario I tried was doing something such as MYNEW_1(Type, Allocator, ConVar1) where ConVar1 would be passed such as
#define MYNEW_1(Type, Allocator, ConVar1) Allocator->Alloc<Type>(sizeof(Type), ConVar1);`
template<typename Type, typename ConVarType>
Type* Alloc(unsigned int size, ConVarType Convar1) // Allocator::Alloc<Type>
{
return (Type*)new(malloc(reportedSize)) Type(Convar1);
}
The problem with this approach is that for my custom Vector, I am also using MYNEW to allocation memory. However, for some Type‘s used for my Vector, there is no default constructor and I can’t tell how many variables the constructor may require.
Does anyone have any insight into how this problem could be solved? (Without of course saying using std:: types instead of my own. I am doing this to learn more). I do not wish to just overload operator new as I have memory tracking in there as I do not wish to have the memory tracked twice (there is more internal tracking to Alloc, but what I have shown is the simplified example) and would rather just use malloc.
It appears that you’re not only doing your own custom allocator, but that you’re also not necessarily trying to define an STL-compatible allocator. However, I think it’s useful to recognize that for all their faults, STL allocators were designed to handle this case. Allocation is separate from construction:
Generally speaking, I believe you have two options: either (1) overload
operator newto handle allocating memory and let the system handle the construction, or (2) make your allocator interface more like the STL allocator interface."Overloading
operator new" is often used to mean two things: (1) replacing it, or (2) adding a new version ofnew. When I originally answered, I was using the first meaning (which really should be called "replacingoperator new" or "overridingoperator new"); but thinking more about this, I’ve determined that truly overloadingoperator newwould meet your requirements.I should mention that the syntax to call an overloaded
operator deleteis so bad that many people avoid this technique for that reason alone. Instead of overloadingdelete, you can create a function (say,deallocate) and use it.The value of this approach is that you follow the language standard of separating memory allocation from object construction, and you leave it up to the compiler to take care of the object construction for you. You don’t have to worry about forwarding operators, or about classes without default constructors, or any of those issues.
Overloading
operator new/operator delete(of course, I’m relying on you to flesh outtrackandrelease):Overloading
operator newand using a functiondeallocate:One case that you should consider is what to do when
newsucceeds but constructing the object fails. That is, when there’s plenty of memory, but some other reason that the object can’t be created. The system is actually smart enough to call the rightdelete(well, thedeletethat has a signature that the system thinks it should have) to release the allocated memory; but only if there is adeletewith that signature. You may well want to overloadoperator deleteand provide adeallocatefunction, with one of them being defined in terms of the other: