2

Why are primitives not default initialized but objects are in C++? For example:

class Foo {
  void Method() {
    int w(); // initialized to 0
    int x; // uninitialized
    std::vector<int> y(); // initialized to empty vector
    std::vector<int> z; // initialized to empty vector
  }
}

In this case, w and y are declared with parentheses, and so are initialized, and z is declared without, and gets its no argument default constructor called, but x remains uninitialized. Why is this?

6
  • 3
    z does have its default constructor called, its just not obvious. Also, with y and w I'm pretty sure you declared a function, not a variable. Commented Dec 20, 2019 at 1:46
  • 2
    int w(); is a declaration for a function named w without parameters and returning int. It is not a variable definition. Similarly y is declared as function returning std::vector<int> without parameters. I think you might want to use {} instead of () to demonstrate your question. Commented Dec 20, 2019 at 1:55
  • @ChrisMM ah yes, the most vexing parse. Commented Dec 20, 2019 at 2:05
  • Because there's no such thing as default initialization of anything in C. Commented Dec 20, 2019 at 2:10
  • recommended watching: youtube.com/watch?v=ZfP4VAK21zc Commented Dec 20, 2019 at 2:51

2 Answers 2

2

If there is no initializer for an object, the object is default initialized [dcl.init]/12. If the initializer is (), the object is value initialized [dcl.init]/11. Default initialization of an object of class type (like std::vector<int>) invokes the default constructor while default initialization for an object of type int means no initialization [dcl.init]/7. Value initialization will also call the default constructor for objects of class type that have one (like std::vector<int> does), but for objects of type int, value initializtion means zero initialization [dcl.init]/8. And zero initialization for an int does actually mean that the int is initialized to zero [dcl.init]/6

As has already been pointed out in the comments,

int w();

and

std::vector<int> y();

are not in fact definitions of a local variable, but rather declarations of two functions w and y that take no arguments and return an int and an std::vector<int> respectively (the infamous most vexing parse). Nevertheless, there are cases where it is possible to use () as an actual initializer, so let's modify your example a bit to demonstrate the behavior you were asking about:

class Foo
{
    int w;
    std::vector<int> y;

    Foo()
      : w(),  // value initialized == zero initialized for int
        y()   // value initialized == default initialized for std::vector<int>
    {
        int x; // default initialized == uninitialized for int
        std::vector<int> z; // default initialized
    }
};
Sign up to request clarification or add additional context in comments.

Comments

1

The "why" here simplifies to "Because C++ was trying to keep performance and behaviors C compatible where it could". When you're selling a new, relatively low-level language that (at least initially) was mostly a superset of C, you don't want to say "If you compile existing C code as C++, it's always slower!" C doesn't zero-initialize primitives by default; as long as the code eventually assigns a value to them before reading from them, that's fine, and C++ follows the same pattern.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.