Initializing Data Members with a Member Function

680 Views Asked by At

I have today learned the very useful new feature of C++ 11 which allows direct initialization of data members in the class declaration:

class file_name
{
    public:
    file_name(const char *input_file_name);
    ~file_name();

    private:
    char *file_name=nullptr;  //data_member is initialized to nullptr;
    char *Allocator(int buffer_size);  //code to dynamically allocate requested
                                       //size block of memory.
};

Is it possible to take this a step further with the new v11 rules and initialize a data member with the output of a member function:

class file_name
{
    public:
    file_name(const char *input_file_name);
    ~file_name();

    private:
    char *file_name=Allocator(MAX_PATH);  //data_member is initialized with a block of
                                          //dynamic memory of sufficient size to hold
                                          //and valid file name.;
    char *Allocator(int buffer_size);  //code to dynamically allocate requested
                                       //size block of memory.
};

Would this cause problems?

2

There are 2 best solutions below

6
On BEST ANSWER

A non-static member function (usually) somehow depends on the state of the object it is called in. If this would not be the case, there would not really be a reason to make it a non-static member function. Now you want to call a function that depends on the state of your object before said object is completely constructed, i.e. its invariants the function might rely on are not necessarily established yet. So using such a function is potentially dangerous since e.g. the function might access uninitialized variables. Consider this example:

class Fail {
    int a = fun() , b;
    int fun() {return b;}
};

Here a gets initialized before b, but with the (undefined) value of b. A static member function should be fine though.

1
On

The brace-or-equal-initializer that you use for member initialisation is defined in the standard, in section 9.2. Point 4 says "A brace-or-equal-initializer shall appear only in the declaration of a data member."

The initialisation of members in the construction process are sescribed in section 12.6.2.
Point 10 describes the order: 1) most derived base class, 2) direct base class initialiser, 3) non static data members 4) compound statement of the constructor.

This means that the base class(es of your class) are always initialised when your data member brace-or-equal-initializer is called.

Point 13 of the section says: "Member functions (including virtual member functions) can be called for an object under construction."... "However, if these operations are performed in a ctor-initializer (or in a function called directly or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the result of the operation is undefined. ". This last exception should not happen in your case.

So yes, this kind of statement should be valid.

Edit: According to 12.6.2 pt.8, the brace-or-equal-initaliszer is only used if the constructor of the object does not have a mem-initializer for the member (i.e. the initializer with ":" syntax)