Does the private new operator have any unexpected side effects?

I read this one on a blog that making a new statement private is a good approach for forcing an instance to be created on the stack.

I am implementing a class that uses the RAII idiom. Obviously this class should only be created on the stack, so I'm looking for a way to provide this.

  • My question is, does it have any side effects that are not straightforward?
  • Is this a good approach to force an instance on the stack?
  • Are there any problems with portability?

Thank you for your help!

EDIT

My RAII class simply creates instances of the various parts of the frame I'm working on, so there is no point in doing anything else with this class than creating an instance on the stack.

The goal is to make it easy to configure to set up the framework and put it in a ready-to-use state without having to create 10 objects in the client code.

+4
source share
3 answers

I am implementing a class that uses the RAII idiom. Obviously this class should only be created on the stack, so I'm looking for a way to provide this.

This is not RAII. RAII is initialized during construction and deinitialization in destructors. RAII are the resources you control (for example, data members), not the lifetime of the "parent" object. Users of your type then reapply RAII to control the lifetime of what they secrete. For example, you can dynamically highlight std :: vector, although the vector uses RAII to make sure that every element that it "owns" is cleared.


My question is, does it have any side effects that are not straightforward to see?

Yes, you are forbidden to use another action (at least with regard to RAII) to use your type.

void example() { shared_ptr<T> p (new T()); // No RAII violation, still uses operator new. vector<T> v (some_initial_size); // No RAII violation, still uses operator new (the placement form is used // inside the default allocator). } 

Is this a good approach to force an instance on the stack?

What are you trying to prevent? What is a use case? Anyone who uses the new with your type either 1) knows what he is doing and needs it, or 2) it will terribly ruin the resource management no matter what you do. You interfere with those in # 1, not helping those in # 2, trying to secure this.

This is another way to state what Steve said:

This class, obviously, should only be created on the stack, so I'm looking for a way to provide this.

If this is obvious, why should this be done?

If users blindly use "new T ()", what makes you think that they will not blindly use ":: new T ()"?


The goal is to make it easy to configure to set up the framework and put it in a ready-to-use state without having to create 10 objects in the client code.

 #include <framework> int main() { framework::Init init; // Do stuff. } 

Use this or something very close to it, which is noticeable in the examples of your documents.

+2
source

This class should obviously only be created on the stack, so I'm looking for a way to provide this.

I think it will not be obvious to users if you must enforce it ...

The main disadvantage is that it does not work.

Even if the new operators are private, users can accidentally use your class as a data member or the base class of their class, and then instantiate the class using new . This stops them writing Foo *f = new Foo(); when they should write Foo f; , but this does not guarantee that their use of your RAII class corresponds to the lexical domain, which probably you really would like to apply.

If someone wants to use a lock (or something else) with dynamic storage duration, then they are either really smart or really stupid. In any case, if you let them create it yourself, you cannot stop their restriction.

What you can do is make all the constructors private (including a copy of ctor), and then provide a friend function that returns a value. They should write:

 const Foo &f = GimmeAFoo(); 

which the standard requires will extend the lifetime of the return value to region f . Since they cannot copy an object, they cannot make a value that goes beyond the scope of the link. Since they cannot initialize a data element or base class, they cannot use a workaround. Note that they must accept a reference to const, however, this does not work if your class needs non-constant members.

They can still do something stupid, for example, to initialize the const reference data element of their own class, but this object cannot escape the area in which this occurs. They will remain sagging like they would if they pointed out that they should not.

+7
source

Even if you cannot prevent others from making the RAII class a base class or a member of a dynamically created object, as Steve said, and you should always inform users of the intended use of this class, it is still a good idea to keep the new operator private so as to prevent the most obvious abuse.

Since this is all valid C ++ code, there are no portability issues.

+2
source

All Articles