Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a private new operator have any unexpected side effects?

I read in this blog, that making the new operator private is a good approach to enforce instantiation on the stack.

I am implementing a class that employs the RAII idiom. This class should obviously only be instantiated on the stack, so I am looking for a way to enforce that.

  • My question is, does this have any side effects that are not straight-forward to see?
  • Is it a good approach to enforce instantiation on the stack?
  • Are there any portability issues?

Thanks for your help!

EDIT

My RAII class just instantiates various parts of the framework I'm working on, so it makes no sense to do anything else with that class than creating an instance on the stack.

The goal is just to provide a simple possiblity to configure the framework and put it in a ready-to-use state, without having to instantiate 10 objects in the client code.

like image 894
theDmi Avatar asked Dec 22 '22 14:12

theDmi


1 Answers

This class should obviously only be instantiated on the stack, so I am looking for a way to enforce that.

I guess it won't be obvious to the users, if you have to enforce it...

The main drawback is that it doesn't work.

Even if the new operators are private, users can still accidentally use your class as a data member or a base class of their own class, and then instantiate their class with new. It stops them writing Foo *f = new Foo(); when they're supposed to write Foo f;, but it doesn't enforce that their use of your RAII class matches lexical scope, which is probably what you'd really like to enforce.

If someone wants to use a lock (or whatever) with dynamic storage duration, then they're either really clever or really stupid. Either way, if you let them create it themselves then you can't stop them getting around your restriction.

What you could do, is make all constructors private (including the copy ctor), then provide a friend function that returns by value. They have to write:

const Foo &f = GimmeAFoo();

which the standard requires will extend the lifetime of the return value as far as the scope of f. Since they can't copy the object, they can't make the value escape the scope of the reference. Since they can't initialize a data member or base class, they can't use the workaround. Note that they have to take a const reference, though, so it doesn't really work if your class needs non-const members.

They can still do something daft, like initialize a const reference data member of their own class like this, but the object itself won't escape the scope in which that happens. They'll be left with a dangling reference, just as they would if they took a pointer to something they shouldn't.

like image 64
Steve Jessop Avatar answered Dec 28 '22 23:12

Steve Jessop