defaulted member function

What does =default mean in:
1
2
3
4
5
struct S {
	int i;
	S(int ii) : i(ii) {}
	S() = default;
};
If you say, it means that the compiler generates definition/implementation for that function, what is that definition/implementation?
Last edited on
It's the same as the implicitly defined default constructor that you would get if you didn't declare any constructors.

It's essentially the same as S(){} except that it doesn't prevent the default constructor from being "trivial" and it can also make a difference if you value-initialize objects of this class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <iomanip>

struct S1
{
	int i;
	S1(int ii) : i(ii) {}
	S1() = default;
};

struct S2
{
	int i;
	S2(int ii) : i(ii) {}
	S2(){};
};

int main()
{
	std::cout << std::boolalpha;
	std::cout << std::is_trivially_default_constructible_v<S1> << "\n"; // true
	std::cout << std::is_trivially_default_constructible_v<S2> << "\n"; // false
	
	std::cout << "\n";
	
	S1 s1{}; // <-- value initialization
	std::cout << s1.i << "\n"; // prints "0"
	
	S2 s2{}; // <-- value initialization
	std::cout << s2.i << "\n"; // This is UB because the s2.i is uninitialized.
}

There might be other minor differences but I think these are the most important ones.
Last edited on
Note that both S1 and S2 leaves i uninitialized if you default-initialize the object.

1
2
3
4
5
S1 s1; // <-- default initialization
std::cout << s1.i << "\n"; // UB (s1.i is uninitialized)

S2 s2; // <-- default initialization
std::cout << s2.i << "\n"; // UB (s2.i is uninitialized) 

Last edited on
1) By "you value-initialize objects" you mean using specifically curly braces for the objects, yeah?

2) The minimal version of the implementations compilers generate for defaulted special member functions are fine only for aggregates or similar simple classes. But for non-trivial classes having pointers or other stuff we can't rely on those default implementations and we should implement them explicitly. Correct?
Last edited on
frek wrote:
1) By "you value-initialize objects" you mean using specifically curly braces for the objects, yeah?

I essentially mean empty curly braces, or empty parentheses where it's not interpreted as a function declaration.

See: https://en.cppreference.com/w/cpp/language/value_initialization

frek wrote:
2) The minimal version of the implementations compilers generate for defaulted special member functions are fine only for aggregates or similar simple classes. But for non-trivial classes having pointers or other stuff we can't rely on those default implementations and we should implement them explicitly. Correct?

For the default constructor I think it depends totally on the member variables and whether default initialization is what you want. For example, a default-initialized std::vector will be empty so if that is what you want then there is no problem.

You can also use default member initializers if default initialization is not what you want.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <vector>

struct Test
{
	std::vector<int> v;
	int i = 73;
	
	Test() = default;
};

int main()
{
	Test t;
	std::cout << t.v.size() << "\n"; // prints "0"
	std::cout << t.i << "\n"; // prints "73"
}

https://en.cppreference.com/w/cpp/language/data_members#Member_initialization
Last edited on
You might be interested in "C++ Initialization story" by Bartek
https://leanpub.com/cppinitbook
I didn't know the story is that massive that needs a book to tell it all!
I have all 5 of the eBooks seeplus mentions and they are worth the effort to buy and read. There's a lot of subtle details about the language that usually get overlooked without in-depth analysis.
Topic archived. No new replies allowed.