Will
Will

Reputation: 1780

The compiler creates a constructor of N args when I have N public member variables and no private ones. What is happening here?

The following code compiles and runs as expected, unless I uncomment one of the two commented out lines that I have labelled with "prevents compilation":

#include <string>
#include <iostream>

class Animal {
    public:
    int count;
    std::string foobar;
    //Animal() = delete; // prevents compilation

    void squeak() const {
        std::cout << count << ". Squeak from " << foobar << std::endl;
    }
    private:
    //int priv; // prevents compilation
};

int main() {  
    std::string foo{"foo"};
    Animal mouse(1, foo);
    //Animal mouse{1, foo};
    //Animal mouse{1, foo, 3};
    mouse.squeak();
    std::cout << "\n";
}

What is happening regarding constructors here, what is this mechanism called and when should one use it?

Upvotes: 0

Views: 40

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275956

This is known as "aggregate initialization".

When your class is an "aggregate", brace-initialization can be used to populate your members. When it is not, it cannot.

Aggregates are classes that are just a bundle of members. Like an aggregate rock, which is made by smooshing together a bunch of different materials.

You are looking at two ways to prevent your class from being an aggregate. One of them is having a private member, and the other is by you explicitly having a constructor.

struct foo {
  int x;
  int y;
};

can be initialized via

foo f = {1,2};

There are a bunch of relatively complex rules about when aggregate initialization occurs. But you ran into the two most common ones here.

For the most part, when you disable aggregate initialization on a class by adding code, the effect is a build break not incorrect code. So it isn't a real huge pain point.

I do strongly advise you to:

int count = 0;
std::string foobar;

initialize ints like that at the point of declaration in a class. This won't block aggregate initialization, but when going from aggregate initialization to non-aggregate initialization variables can become uninitialized in some situations if you don't do this.

Upvotes: 1

Related Questions