-1

c++ primer says :

The default constructor is used automatically whenever an object is default or value initialized.
Default initialization happens
• When we define nonstatic variables (§ 2.2.1, p. 43) or arrays (§ 3.5.1, p. 114) at block scope without initializers
• When a class that itself has members of class type uses the synthesized de- fault constructor (§ 7.1.4, p. 262)
• When members of class type are not explicitly initialized in a constructor initializer list (§ 7.1.4, p. 265)
Value initialization happens
• During array initialization when we provide fewer initializers than the size of the array (§ 3.5.1, p. 114)
• When we define a local static object without an initializer (§ 6.1.1, p. 205) • When we explicitly request value initialization by writing an expressions of the form T() where T is the name of a type (The vector constructor that takes a single argument to specify the vector’s size (§ 3.3.1, p. 98) uses an argument of this kind to value initialize its element initializer.)
Classes must have a default constructor in order to be used in these contexts. Most of these contexts should be fairly obvious

class foo{
public :
    int data;
    foo() = default;
};

int main(){
    std::vector<foo> fvec1;
    std::vector<foo> fvec2(4,foo(2));
    foo f[5]{1,2,4};
    std::cout << fvec2[1].data << " " << f[4].data << std::endl;
}

Output :

error: no matching function for call to ‘foo::foo(int)’
    std::vector<foo> fvec2(4, foo(2));
                              ^
error: could not convert ‘1’ from ‘int’ to ‘foo’
       foo f[5]{1,2,4};
                ^

But if we remove the following line

foo() = default;

the code works, while synthesised default constructor is used, why not a default constructor declared as default, why I am not getting the default behaviour though declared default.
And if possible can any one provide examples for above reasons said by 'c++ primer', because it is so confusing.

standard : c++ 20
compiler : g++-12, clang++-15

4
  • What version of C++ are you compiling against, that will matter. Commented Dec 22, 2023 at 13:53
  • updated c++ standard as pointed by @NathanOliver Commented Dec 22, 2023 at 14:19
  • Because in C++20 when you remove the defaulted ctor, it becomes an aggregate and there is parenthesis aggregate initialization in c++20 Commented Dec 22, 2023 at 14:25
  • @semicolon_missing Keep in mind that the book you're using is C++11 only while you're compiling your program using C++20. Commented Dec 22, 2023 at 14:39

1 Answer 1

2

So we have a couple of things going on here. First is that foo in the form of

class foo{
public :
    int data;
};

is an aggregate. An aggregate can be initialized with {} and beginning in C++20 that was expanded to include () for initialization as well. That means in

std::vector<foo> fvec2(4,foo(2));
//and
foo f[5]{1,2,4}

that you aggregate initialize the objects.

When you change foo to

class foo{
public :
    int data;
    foo() = default;
};

You no longer have an aggregate because you have a user declared constructor. This means that to value initialize it you need to provide a constructor that takes in the value(s) that are needed to construct the class. You do that by adding a constructor like

class foo{
public :
    int data;
    foo() = default;
    foo(int data_) : data(data_) {}
};
Sign up to request clarification or add additional context in comments.

2 Comments

There are already plenty of duplicates for this.
@user12002570 I don't think there are many that also explain that () is usable in aggregate initialization since it is a pretty new feature. If you find one go ahead and close it and I'll delete my answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.