Reputation:
Is it possible to overload the new
operator so that an object isn't created, but instead return an existing object.
If that is possible, how could you create the objects in the first place :D
This sounds weird I know. I'm trying to hide some details from the client. I am making a game on PS2, I'd like to have the New Foo()
syntax but want a list of premade objects that can be used instead.
I don't see to circumvent this as the new operator returns a pointer to available memory.
new Foo;
struct Foo
{
void* operator new(std::size_t)
{
// return pre made obj.
}
};
Upvotes: 1
Views: 1889
Reputation: 31
The thing about using operator ::new is that the compiler will automatically generate an opcode to call the constructor after the call to new, so new itself isn't in charge of the constructor. What you want is either a singleton:
struct Foo
{
static Foo& NewObject()
{
static Foo* _foo = new Foo;
return *_foo;
}
}
or some kind of array:
struct Foo
{
static Foo& NewObject()
{
static Foo* _foo = new Foo[128];
static int index = 0;
if(index == 128)
index = 0;
return _foo[index++];
}
}
Upvotes: 0
Reputation: 6089
http://www.cplusplus.com/reference/std/new/operator%20new%5B%5D/
Should tell you all you need to know!
or maybe even this
http://www.cplusplus.com/reference/std/new/operator%20new/
operator new is a global function which you can override.
Don't forget you need to also provide an operator delete, if you provide an operator new.
I'm guessing you are trying to set up a memory pool, remember to actually measure performance with and without, as its not always worth the hassle IMHO.
Edit: Reading between the lines of your question and some of the other answers, my guess is you really want to leave overloading new / delete and singleton pattern alone. Instead go for a factory pattern approach.
All of your code calls a
SomethingStatic::GetNewWhatsit()
function, (instead of constructing the object) which returns the next pointer in an array. An array of pointers to objects which you created in the normal way in the initialisation of your program.
whatsit* GetNewWhatsit()
{
if (num_of_objects > ARRAY_SIZE(whatsit_cache))
return 0;
else
return whatsit_cache[num_of_objects++]; // post inc. on purpose
}
Upvotes: 4
Reputation: 9817
I would suggest using the bridge pattern.
This means that your client can call new as normal on a trivial public class that internally makes the choice about what to construct or not construct.
The contained class can be private to your library.
Upvotes: 0
Reputation: 35449
Not only you can't modify operator new
to do what you want (it's an allocation function only), you shouldn't. Subverting the meaning of a new expression would make your code harder to understand, for no benefits at all.
If you want brand new functionality, then write code! Here, what you need might be a class (we can't tell), or maybe just be a function:
template<typename T, typename... U>
std::shared_ptr<T> // for one std::shared_ptr seems appropriate
make(U&&... u);
The client code then uses this factory-like function to obtain the objects it needs. What does the function actually do? Does it cache objects using a Flyweight pattern? Does it cache memory instead of objects? The client code doesn't care and doesn't want to. All it cares is that it obtains the object it asks for.
Meanwhile, the code in the function does whatever it needs to. If tomorrow you realize you got it wrong, you can change the code inside and hopefully it won't affect the rest. At least it has a fighting chance to.
Upvotes: 0
Reputation: 279255
You can overload operator new
, but that overloaded operator doesn't return an object. It returns the memory for an object, and the implementation arranges for the constructor to be called.
So you can't do quite what you want.
Instead, if the cost you're trying to avoid is that of memory allocation, then your overload can assign some memory from a pre-allocated block. Obviously you're then responsible for tracking what's free and what isn't, and your challenge is to do this more efficiently than the allocator that comes with the PS2 devkit. That might not be too hard - you have an unfair advantage if you're only dealing with one class, and assuming nobody derives from it, that the size of the allocations is fixed.
If the cost you're trying to avoid is that of calling the constructor, then operator new
doesn't help you, but you could write a sort of wrapper:
struct FooWrapper {
Foo *foo;
FooWrapper(): foo(choose_a_pre_existing_foo()) { }
~FooWrapper() {
foo->reset(); // clear up anything that shouldn't be kept
return_to_the_pool_for_reuse(foo);
}
private:
FooWrapper(const FooWrapper &);
FooWrapper &operator=(const FooWrapper &);
};
Foo *choose_a_pre_existing_foo() {
// possibly some kind of synchronization needed if list is global
// and program is multi-threaded.
if list_of_foos.empty() {
return new Foo();
} else {
Foo *f = list_of_foos.back();
list_of_foos.pop_back();
return f;
}
}
Upvotes: 3
Reputation: 24212
If you want a single object, the Singleton pattern can be used. If you want multiple objects, you need an object pool.
Upvotes: 1
Reputation: 33395
Overloading new
is fraught with peril. It's more than just C++'s malloc
, it has important semantics for object lifetimes and exception safety and so on.
When you call new
the constructor gets called. You don't want to construct an object twice because you can't sensibly destroy it twice. At best you will leak resources.
You might want more than a mere singleton, maybe try something like this:
foo.h
struct Foo {
static Foo instance_a;
static Foo instance_b;
enum Predefined {
ALICE,
BOB
};
static Foo & instance (Predefined);
// ...
}
foo.cpp
Foo Foo :: instance_a (1, 2, 3);
Foo Foo :: instance_b ("alpha");
namespace {
Foo alice;
Foo bob (1, "x");
}
Foo & Foo :: instance (Predefined name) {
// ...
return alice;
}
Loads of possibilities.
Upvotes: 1
Reputation: 41331
As far as I know, you can't change this aspect of new that it actually constructs the object. The overloaded operator just returns raw memory, and then the language constructs the object automatically in this memory. You don't control that step.
Anyway, if you don't get a new object, what would be the point of that syntax?
Upvotes: 6