I'd like to keep MyClass in the stack memory (simpler, faster) in the following code, but avoid calling the default constructor:
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "MyClass()" << std::endl;
}
MyClass(int a) {
std::cout << "MyClass(" << a << ")" << std::endl;
}
MyClass(const std::string& a) {
std::cout << "MyClass(\"" << a << "\")" << std::endl;
}
void doStuff() {
std::cout << "doStuff()" << std::endl;
}
};
int main(int argc, char* argv[]) {
bool something;
if (argc > 1)
something = 1;
else
something = 0;
MyClass c;
if (something)
c = MyClass(1);
else
c = MyClass("string");
c.doStuff();
return 0;
}
As far as I know, the only way to avoid calling the default constructor would be to use a pointer, but then I would have to allocate in the heap and deal with memory management. Is there any other way?
We can allocate variable length space dynamically on stack memory by using function _alloca. This function allocates memory from the program stack. It simply takes number of bytes to be allocated and return void* to the allocated space just as malloc call.
A constructor does not allocate memory for the class object its this pointer refers to, but may allocate storage for more objects than its class object refers to. If memory allocation is required for objects, constructors can explicitly call the new operator.
In C language, we use the malloc() or calloc() functions to allocate the memory dynamically at run time, and C++ also supports these functions. But, in C++, allocation and deallocation are done manually.
malloc is used to allocate memory. You can use a pointer by either allocating it with malloc or making it point to an already allocated portion of memory.
If you don't mind using a total hack, you can try a placement new
.
char mem[sizeof(MyClass)] alignas(MyClass);
auto custom_deleter = [](MyClass *p){ p->~MyClass(); };
std::shared_ptr<MyClass> c(new (mem) MyClass, custom_deleter);
You use the alignas
to make sure the automatic memory allocated is properly aligned for your object. The custom_deleter
function calls the destructor without freeing the memory, which is needed when using automatic memory with a smart pointer. A demo of the code can be found here.
But, for your problem a more elegant solution exists. You can use a copy constructor instead:
MyClass c = something ? MyClass(1) : MyClass("string");
c.doStuff();
You're right. It isn't possible for you do avoid calling the default constructor, unless you want to duplicate some code like shown below.
if (something) {
MyClass c(1);
c.doStuff();
}
else {
MyClass c("string");
c.doStuff();
}
I would recommend that you create the object of the heap, but delegate the memory handling to another class. With C++03, there is the std::auto_ptr class which can be used. With C++11, auto_ptr has be deprecated, and instead you can use shared_ptr or unique_ptr.
Here is some example code using shared_ptr -
std::shared_ptr<MyClass> c;
if (something)
c.reset(new MyClass(1));
else
c.reset(new MyClass("string"));
c->doStuff();
The object will automatically be deleted when it goes out of scope.
In general, it is recommended to use smart pointers instead of doing the memory management yourself. This is especially useful when you're dealing with code that can throw exceptions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With