9

I came across a statement in my book that said:

You don't have to initialize a static member when you declare it; C++ will invoke the default constructor if you don't.

This really has me confused as to what it means. Are they talking about object members only? If so, at what point would it call the default constructor? Also, how would you initialize a static member object without the default constructor?

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
rubixibuc
  • 7,111
  • 18
  • 59
  • 98

4 Answers4

18

Let's break it down. Suppose there's some class Foo; somewhere. Now we make this a static member of our class,

class Star
{
  static Foo z;
  // ...
};

Now in essence that declares a global object Foo Star::z -- so how does this get instantiated? The standard tells you: it gets default-constructed. But remember that you have to provide the actual object instance in one of your translation units:

// in, say, star.cpp
Foo Star::z;  // OK, object lives here now


Now suppose that Foo doesn't actually have a default constructor:

class Foo
{
public:
  Foo(char, double); // the only constructor
  // ...
};

Now there's a problem: How do we construct Star::z? The answer is "just like above", but now we have to call a specific constructor:

// again in star.cpp
Foo Star::z('a', 1.5);


The standard actually has two distinct notions of "initialization" (a grammatical concept) and "construction" (a function call), but I don't think we need to go into this just now.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • what if the static member is eg an `int` and I write only `int Star::z;` in the cpp? Is it default initialized to 0? – 463035818_is_not_an_ai Jul 24 '17 at 19:20
  • 1
    @tobi303: Yes, objects with static storage duration are zero-initialized first if they are not otherwise constant-initialized (even if they are later initialized dynamically). – Kerrek SB Jul 24 '17 at 19:46
2

In C++, new objects are always initialized somehow. There's default initialization, copy initialization, value initialization, and direct initialization, the only question is which one your code is using.

I assume they mean:

SomeObject SomeClass::x; // default initialization, class types will have the default constructor called

vs

SomeObject SomeClass::x = blah; // copy initialization

The copy constructor is needed, possibly there's also a conversion of blah to a temporary SomeObject before calling the copy constructor, and sometimes the call to the copy constructor is skipped, but it must be accessible.

If you don't want to call the default or copy constructor, use direct initialization syntax:

SomeObject SomeClass::x(blah); // direct initialization
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • He said 'declare', not 'define', which is what makes the question so confusing. – ildjarn Sep 09 '11 at 23:08
  • 1
    @ildjarn: A definition is a kind of declaration. But the book is clearly inaccurate. – Ben Voigt Sep 09 '11 at 23:10
  • In the case of ODR-used static data members, the definition must always be separate from the declaration, so I don't think that's relevant in this case. But yes, I'm eager to see what book it is that's spreading this misinformation. – ildjarn Sep 09 '11 at 23:14
  • The book is c++ for dummies, I glad that it doesn't make sense to anyone else, because it sure didn't to me :-/ – rubixibuc Sep 09 '11 at 23:18
  • 3
    @rubixibuc : 'for Dummies' books tend to be written by dummies it seems. ;-] I'd recommend throwing it away and getting one (or more) of the books listed in [this FAQ](http://stackoverflow.com/q/388242/636019) instead. – ildjarn Sep 09 '11 at 23:21
  • Thank you :-) I'll look the list over – rubixibuc Sep 09 '11 at 23:46
1

In this statement: "You don't have to initialize a static member when you declare it; C++ will invoke the default constructor if you don't." "The static member" means the "static member" of some primitive types member variable, in another word, the data types of the "static member" should only be: int, float, or char..... So for these primitive types, compiler know their "default constructor", e.g. for the "int" type, compiler just set 0. But if these static members types are specific classes, not those C++ built-in primitive types, you must call the specific constructor function explicitly, it's exactly same as the 1st answer provided by "Kerrek SB" But remember one thing, even your static member's type is primitive type, you still need declare its implementation in the *.c file. Assume in the example provided by "Kerrek SB", if we change the:

class Star
{
  static Foo z;
  // ...
};

to

class Star
{
  static int z;
  // ...
};

in the star.h file, we still need to add one line in star.c as:

// again in star.cpp
int Star::z;

It'll be initialized as 0 by compiler; So I believe the "static member" in in "You don't have to initialize a static member" only means "static member" whose type is C++ primitive type. If its type are some classes, you must call their specific constructor function as same as any other classes' objects.

Clock ZHONG
  • 875
  • 9
  • 23
  • 1
    You imply that the compiler can't automatically call the default constructor for objects of user-defined types, which is false. It certainly can, and it very frequently does. The default constructor of a UDT can be invoked implicitly by defining as `SomeObject my Obj;` or explicitly with `SomeObject myObj{}; // or ()`. – underscore_d Apr 16 '16 at 17:48
  • underscore_d, I didn't say so. This topic is talking about the static member's type in another class, instead of a general variable's type initialization. If you believe "static SomeObject myObj" could be defined in your another class, please just design a small test to prove it. I did it, it couldn't work and report compiling errors. – Clock ZHONG Apr 17 '16 at 02:49
1

Edit: Moving the comment to answer.

member is by definition always an object member as it means a declared variable as a member of an object. That said static members need to be forward declared and it's generally good practice to explicitly initialize variables. What book is this?

// SomeObject.h
class SomeObject
{
public:
   SomeObject(); // default constructor
private:
   // declare members
   int m_intMember;
   static int m_staticIntMember;
};

// SomeObject.cpp
#include "SomeObject.h"

// forward declaration and initializing of static member
int SomeObject::m_staticIntMember(42); 

SomeObject::SomeObject() : m_intMember(7) // initializing other member
{
}
AJG85
  • 15,849
  • 13
  • 42
  • 50