Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Creating an uninitialized placeholder variable rather than a default object

I'm moving from Java to C++ right now and I'm having some difficulties whenever a commonly used concept in Java doesn't map directly into C++. For instance, in Java I would do something like:

Fruit GetFruit(String fruitName) {
    Fruit fruit;
    if(fruitName == "apple") fruit = new Fruit("apple");
    else if(fruitName == "banana") fruit = new Fruit("banana");
    else fruit = new Fruit("kumquat"); //'cause who really wants to eat a kumquat?

    return fruit;
}

Of course, in C++ the Fruit fruit; statement actually creates a fruit. Does this mean I have to have a default constructor? This seems unsafe! What if my default fruit escaped?

like image 509
JnBrymn Avatar asked Jul 20 '10 15:07

JnBrymn


People also ask

What is uninitialized variable in C++?

An uninitialized variable is a variable that has not been given a value by the program (generally through initialization or assignment). Using the value stored in an uninitialized variable will result in undefined behavior.

Why “always initialize your variables”?

This is the primary reason for the “always initialize your variables” best practice. Using the value from an uninitialized variable is our first example of undefined behavior.

When an object is not initialized but assigned a value?

Therefore, an object that is not initialized but is then assigned a value is no longer uninitialized (because it has been given a known value). Initialization = The object is given a known value at the point of definition.

Is it legal to initialize a variable to 0?

Note: Variables with static or thread local storage, including global variables without the static keyword, are initialized to either zero, or their initialized value. Hence the following is legal. A very common mistake is to not initialize the variables that serve as counters to 0.


3 Answers

C++ gives you much more headache when it comes to creating fruits. Depending on your needs, you can choose one of the following options:

1) create a Fruit on a stack and return a copy (you need a copy constructor) then and must provide some default fruit in case the name does not match:

Fruit GetFruit(const std::string &name)
{
   if ( name == "banana" ) return Fruit("banana");
   if ( name == "apple" )  return Fruit("apple");
   return Fruit("default");
}

2) create a Fruit on a heap and take care, that there could be null-pointer returned and also remember to delete this fruit somewhere and take care that it is deleted only once and only by its owner (and take care that noone holds a pointer to the deleted fruit):

Fruit* GetFruit(const std::string &name)
{
   if ( name == "banana" ) return new Fruit("banana");
   if ( name == "apple" )  return new Fruit("apple");
   return NULL;
}

3) and finally, use a smart pointer to avoid many possible pointer problems (but take care of null pointers). This option is the closest to your Java programming experience:

typedef boost::shared_ptr<Fruit> FruitRef;

FruitRef GetFruit(const std::string &name)
{
   if ( name == "banana" ) return new Fruit("banana");
   if ( name == "apple" )  return new Fruit("apple");
   return FruitRef();
}
like image 183
SadSido Avatar answered Oct 26 '22 08:10

SadSido


Objects in Java are represented by pointers. Since this is pervasive, there is no special notation for pointers. In C++, objects can be represented by themselves or by pointers, so it's necessary to specify pointers when they occur.

The C++ version of your code is:

Fruit * GetFruit(std::string fruitName) {
    Fruit * fruit = 0;
    if (fruitname == "apple") fruit = new Fruit("apple");
    else if (fruitname == "banana") fruit = new Fruit("banana");
    else fruit = new Fruit("kumquat");

    return fruit;
}

This returns a pointer to Fruit. You would access members like fruit->color(), not fruit.color(). You should delete that pointer when you're through with it.

like image 42
David Thornley Avatar answered Oct 26 '22 10:10

David Thornley


The most straightforward way would be:

Fruit GetFruit(String fruitName) {
    if(fruitName == "apple") return Fruit("apple");
    else if(fruitName == "banana") return Fruit("banana");
    else fruit = return Fruit("kumquat"); //'cause who really wants to eat a kumquat?
}

... and a direct mapping would be to use a (preferably "smart") pointer:

auto_ptr<Fruit> GetFruit(String fruitName) {
    auto_ptr<Fruit> fruit;
    if(fruitName == "apple") fruit = new Fruit("apple");
    else if(fruitName == "banana") fruit = new Fruit("banana");
    else fruit = new Fruit("kumquat"); //'cause who really wants to eat a kumquat?
    return fruit;
}
like image 40
Éric Malenfant Avatar answered Oct 26 '22 10:10

Éric Malenfant