3

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?

  • Right you are - I wrote it off the top of my head, as I tend to pass all variables by reference. Perhaps wrongly? Altered in OP. –  Aug 08 '14 at 20:06
  • To pass that pointer by reference you'd have to declare it as `const char *&input_file_name`, not as your original `const char &*input_file_name`. – AnT stands with Russia Aug 08 '14 at 21:42
  • Mmmmmm... Counter-Intuitive. As Homer might say. –  Aug 08 '14 at 23:41

2 Answers2

1

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.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • In my case the allocator is purely a worker function and has no effect on the object as a whole. I only put it inside a function so I can catch any - unlikely it seems - exceptions from calling _new[]_. I guess I could even put it in an external library and statically link to it, however that seems a bit excessive. –  Aug 08 '14 at 20:03
  • 1
    If it does not depend on the objects state, you can just declare it `static`. (This has nothing to do with external libraries.) Then the compiler will protect you from mistakes. – Baum mit Augen Aug 08 '14 at 20:05
  • Can you declare functions as 'static'? Interesting! This is why I keep coming back to C++ - there is so much to explore! –  Aug 08 '14 at 20:09
  • You mentioned declaring the function as `static` protects you from errors. Could you explain what those errors might be that `static` helps to avoid? –  Aug 08 '14 at 20:17
  • 1
    [It does not let you do what I did in my answer.](http://coliru.stacked-crooked.com/a/ebcec7278277e5b9) – Baum mit Augen Aug 08 '14 at 20:18
  • 1
    Ahhh... I think I am with you then. Basically, as `static` member functions have no `this` pointer they cannot directly change data members of their parent class. Excellent! –  Aug 08 '14 at 20:23
0

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)

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • 1
    By the way, I could compile the code with MSVC 2013, with 2 adjustments: 1) `const char *&input_file_name`, 2) rename of the private member because it was not allowed to carry the same name as the class itself. – Christophe Aug 08 '14 at 20:19