Search code examples
c++stackraiinew-operator

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.


Solution

  • 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.

    That is not RAII. RAII is initializing when constructing and de-initializing in destructors. RAII is about resources you control (e.g. data members) and not the lifetime of the "parent" object. Users of your type then again apply RAII to control the lifetime of what they allocate. For example, you can dynamically allocate a std::vector, even though vector uses RAII to make sure every item it "owns" is cleaned up.


    My question is, does this have any side effects that are not straight-forward to see?

    Yes, you prevent otherwise valid (at least as far as RAII is concerned) uses of 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 it a good approach to enforce instantiation on the stack?

    What are you trying to prevent? What is the use case? Anyone who uses new with your type either 1) knows what they're doing and needs it, or 2) will screw up resource management horribly no matter what you do. You hinder those in #1 without helping those in #2 by attempting to enforce this.

    This is another way to state what Steve said:

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

    If that is obvious, why does it need to be enforced?

    If users will blindly use "new T()", what makes you think they won't blindly use "::new T()"?


    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.

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

    Use this, or something very close to it, prominently in your docs' examples.