Anubhav asked:
An interesting question has come up in our project while debating operator new as a class member function. Specifically, the question is about whether such a class should be allowed to be instantiated on stack. The understanding is that a class providing its own operator new would likely have special layout considerations which would not be met if the object of such a class is instantiated locally.
The class specific operator new is used when allocating on the heap, but objects can still be allocated on the stack. The only way I know to prevent an object from being instantiated on the stack is by forcing creation through a factory function that always allocates on the heap, for example:
#include <memory>
class X {
// make all ctors private
X();
X(const X&);
// and any other ctors go here
public:
// Factory function (or it could be a nonmember friend)
static auto make( /*…*/ ) { return std::unique_ptr<X>(new X( /*…*/ )); }
// the usual public member functions go here
};
int main()
{
X x; // error
auto x2 = X::make(); // ok
}
How about the protected destructor solution?
For instance, as suggested here:
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Requiring_or_Prohibiting_Heap-based_Objects
But std::make_unique also requires access to the constructor, right? X::make could create the unique_ptr manually instead.
@mttpd: The protected destructor solution also works, but it’s a C++98 idiom that’s now inferior because it requires using a custom ‘deleter’ function that is possible, but less natural and idiomatic in modern C++, to use together with unique_ptr and shared_ptr.
@Petter: Good point, thanks. Fixed.
@Good point, thanks. Fixed.
But this also gives up on the perf and memory layout advantages of std::make_shared… In library code this could be premature pessimisation. What about:
class X
{
//make all ctors private
struct PrivateConstructionTag {};
public:
static auto make( /*…*/ ) { return std::make_shared( /*…*/ PrivateConstructionTag()); }
};
I’m using this pattern in my library code. Is this the best solution?
Correction:
should be
Hi. Does
std::make_unique
have the same problems with the private constructor pattern asstd::make_sharedcode> have? I.e. that it is not portably possible to make
std::make_shared
a friend ofX
in the example. What is the preferred way to solve this problem? Is the use of thePrivateConstructorTag
the only way?If
is the plan anyway, then deriving from
may be adequate. No?
@Grout: Deriving from
enable_shared_from_this
doesn’t actually block compilation of code that instantiates the object on the stack. Nor does it block compilation ofnew Foo()
. I have found thePrivateConstructorTag
to be the best way to ensure that a class that inherits fromenable_shared_from_this
is only constructed withmake_shared()
.My idea is a wrapper around. Is there any issues?