Is it possible to declare a variable in c++ without instantiating it? I want to do something like this:
Animal a;
if( happyDay() )
a( \"puppies\" ); //c
Since c++17, there is now an overhead-free way to do this: std::optional. The code in this case would be:
#include <optional>
std::optional<Animal> a;
if(happyDay())
a.emplace("puppies");
else
a.emplace("toads");
In addition to Greg Hewgill's answer, there are a few other options:
Lift out the main body of the code into a function:
void body(Animal & a) {
...
}
if( happyDay() ) {
Animal a("puppies");
body( a );
} else {
Animal a("toad");
body( a );
}
(Ab)Use placement new:
struct AnimalDtor {
void *m_a;
AnimalDtor(void *a) : m_a(a) {}
~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); }
};
char animal_buf[sizeof(Animal)]; // still stack allocated
if( happyDay() )
new (animal_buf) Animal("puppies");
else
new (animal_buf) Animal("toad");
AnimalDtor dtor(animal_buf); // make sure the dtor still gets called
Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf));
... // carry on
I prefer Greg's answer, but you could also do this:
char *AnimalType;
if( happyDay() )
AnimalType = "puppies";
else
AnimalType = "toads";
Animal a(AnimalType);
I suggest this because I've worked places where the conditional operator was forbidden. (Sigh!) Also, this can be expanded beyond two alternatives very easily.
If you want to avoid garbage collection - you could use a smart pointer.
auto_ptr<Animal> p_a;
if ( happyDay() )
p_a.reset(new Animal( "puppies" ) );
else
p_a.reset(new Animal( "toads" ) );
// do stuff with p_a-> whatever. When p_a goes out of scope, it's deleted.
If you still want to use the . syntax instead of ->, you can do this after the code above:
Animal& a = *p_a;
// do stuff with a. whatever
You can't use references here, since as soon as you'd get out of the scope, the reference would point to a object that would be deleted.
Really, you have two choices here:
1- Go with pointers:
Animal* a;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
// ...
delete a;
2- Add an Init method to Animal
:
class Animal
{
public:
Animal(){}
void Init( const std::string& type )
{
m_type = type;
}
private:
std:string m_type;
};
Animal a;
if( happyDay() )
a.Init( "puppies" );
else
a.Init( "toads" );
I'd personally go with option 2.
Yes, you can do do the following:
Animal a;
if( happyDay() )
a = Animal( "puppies" );
else
a = Animal( "toads" );
That will call the constructors properly.
EDIT: Forgot one thing... When declaring a, you'll have to call a constructor still, whether it be a constructor that does nothing, or still initializes the values to whatever. This method therefore creates two objects, one at initialization and the one inside the if statement.
A better way would be to create an init() function of the class, such as:
Animal a;
if( happyDay() )
a.init( "puppies" );
else
a.init( "toads" );
This way would be more efficient.