سؤال

Is there a simpler way for a class's constructor to specify that all members of built-in type should be zero-initialized?

This code snippet came up in another post:

struct Money
{
    double amountP, amountG, totalChange;
    int twenty, ten, five, one, change;
    int quarter, dime, nickel, penny;

    void foo();
    Money()  {}
};

and it turned out that the problem was that the object was instantiated via Money mc; and the variables were uninitialized.

The recommended solution was to add the following constructor:

Money::Money()
  : amountP(), amountG(), totalChange(),
    twenty(), ten(), five(), one(), change()
    quarter(), dime(), nickel(), penny()
{
}

However, this is ugly and not maintenance-friendly. It would be easy to add another member variable and forget to add it to the long list in the constructor, perhaps causing a hard-to-find bug months down the track when the uninitialized variable suddenly stops getting 0 by chance.

هل كانت مفيدة؟

المحلول

You can use a subobject to initialize en masse. A member works, but then you need to qualify all access. So inheritance is better:

struct MoneyData
{
    double amountP, amountG, totalChange;
    int twenty, ten, five, one, change;
    int quarter, dime, nickel, penny;
};

struct Money : MoneyData
{
    void foo();
    Money() : MoneyData() {} /* value initialize the base subobject */
};

Demonstration (placement new is used to make sure the memory is non-zero before object creation): http://ideone.com/P1nxN6

Contrast with a slight variation on the code in the question: http://ideone.com/n4lOdj

In both of the above demos, double members are removed to avoid possible invalid/NaN encodings.

نصائح أخرى

For something working in C++98, you can use Boost's value_initialized: (live example)

#include <boost/utility/value_init.hpp>
...
struct Money
{
    boost::value_initialized<double> amountP, amountG, totalChange;
    boost::value_initialized<int> twenty, ten, five, one, change;
    boost::value_initialized<int> quarter, dime, nickel, penny;

    void foo();
    Money()  {/*every member is 0*/}
};

You can use the default constructor the following way

Money m = {};

Or you can set initialization of data members inside the class definition:

struct Money
{
    double amountP = 0.0, amountG = 0.0, totalChange = 0.0;
    int twenty = 0, ten = 0, five - 0, one = 0, change = 0;
    int quarter = 0, dime = 0, nickel = 0, penny = 0;

    void foo();
    Money()  {}
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top