C++ class that can be put *only* on the stack?
The following class allows only: X&& x = X::MakeInstance();
or const X& x = X::MakeInstance();
usages:
class X
{
public:
X(const X&) = delete;
X(X&&) = delete;
X& operator =(const X&) = delete;
X& operator =(X&&) = delete;
public:
static X MakeInstance() { return {}; }
static void* operator new (size_t) = delete;
static void* operator new[] (size_t) = delete;
static void operator delete (void*) = delete;
static void operator delete[](void*) = delete;
private:
X() = default;
};
How to prevent others create a new instance of a class on heap?
I think the best you can do is to declare a private
operator new
(I can't recall if this is needed but you'll probably want to do all three: normal, array, and placement) in your base class. The user can still get around this by creating their own operator new
in the Derived class but at least they have to think about it and actively work to subvert your intention.
If you're worried about non-accidental problems with creating your class on the heap (for example malicious developers of child classes), C++ is not the language for this project. It's powerful and has lots of places where your have to rely on your end-programmers not bypassing the intentions.
Is it possible to prevent stack allocation of an object and only allow it to be instantiated with 'new'?
One way you could do this would be to make the constructors private and only allow construction through a static method that returns a pointer. For example:
class Foo
{
public:
~Foo();
static Foo* createFoo()
{
return new Foo();
}
private:
Foo();
Foo(const Foo&);
Foo& operator=(const Foo&);
};
Why would you ever make operator `new` private?
Lots of embedded C++ need to guarantee that NO dynamic allocations are done once the system is started. The aeronautics, automotive and medical device industry often have this requirement. See the following links for such coding standards and the rational behind it:
- http://www.stroustrup.com/JSF-AV-rules.pdf
- http://www.qa-systems.com/tools/qa-misra/
Class constructed only on stack; not with new. C++
Make your operator new
private.
#include <new>
struct Foo {
int x;
private:
void* operator new (std::size_t size) throw (std::bad_alloc);
};
On C++0x you can delete
the operator new
:
struct Foo {
int x;
void* operator new (std::size_t size) throw (std::bad_alloc) = delete;
};
Note that you need to do the same for operator new[]
separately.
C++ - Prevent global instantiation?
Instead of placing somewhat arbitrary restrictions on objects of your class I'd rather make the calls to the C API safe by wrapping them into a class. The constructor of that class would do the initialization and the destructor would release acquired resources.
Then you can require this class as an argument to your class and initialization is always going to work out.
The technique used for the wrapper is called RAII and you can read more about it in this SO question and this wiki page. It originally was meant to combine encapsulate resource initialization and release into objects, but can also be used for a variety of other things.
why would I forbid allocation in the heap?
Some classes make sense only if the objects are instantiated on the stack. For example, Boost scoped_ptr, or lock_guard.
Related Topics
Inheritance and Method Overloading
Specialization of Templated Member Function in Templated Class
How to Convert Char* to Lpcwstr
The Precision of Std::To_String(Double)
Std::Vector Iterator Invalidation
Why Does Calling Method Through Null Pointer "Work" in C++
Why Doesn't Left Bit Shift << Shift Beyond 31 for Long Int Datatype
How to Read Files in Sequence from a Directory in Opencv
What Is the Type of a String Literal in C++
Virtual Destructor and Undefined Behavior
How to Use Createthread for Functions Which Are Class Members
<Iostream> VS. <Iostream.H> VS. "Iostream.H"
Trouble Launching Cuda Kernels from Static Initialization Code
Portability of #Warning Preprocessor Directive
Is There a Compiler Bug Exposed by My Implementation of an Is_Complete Type Trait
"If Constexpr" in C++17 Does Not Work in a Non-Templated Function