"""
Value-initialization
C++ C++ language Initialization
This is the initialization performed when an object is constructed with an empty initializer.

Syntax
T () (1)
new T () (2)
Class::Class(...) : member () { ... } (3)
T object {}; (4) (since C++11)
T {} (5) (since C++11)
new T {} (6) (since C++11)
Class::Class(...) : member {} { ... } (7) (since C++11)
Explanation
Value-initialization is performed in these situations:

1,5) when a nameless temporary object is created with the initializer consisting of an empty pair of parentheses or braces(since C++11);
2,6) when an object with dynamic storage duration is created by a new expression with the initializer consisting of an empty pair of parentheses or braces(since C++11);
3,7) when a non-static data member or a base class is initialized using a member initializer with an empty pair of parentheses or braces(since C++11);
4) when a named object (automatic, static, or thread-local) is declared with the initializer consisting of a pair of braces.
In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate initialization is performed instead of value-initialization.

If T is a class type that has no default constructor but has a constructor taking std::initializer_list, list-initialization is performed.

(since C++11)
The effects of value-initialization are:

If T is a (possibly cv-qualified) class type:
If the default-initialization for T selects a constructor, and the constructor is not user-declared(until C++11)user-provided(since C++11), the object is first zero-initialized.
In any case, the object is default-initialized.
Otherwise, if T is an array type, each element of the array is value-initialized.
Otherwise, the object is zero-initialized.
Notes
The syntax T object(); does not initialize an object; it declares a function that takes no arguments and returns T. The way to value-initialize a named variable before C++11 was T object = T();, which value-initializes a temporary and then copy-initializes the object: most compilers optimize out the copy in this case.

References cannot be value-initialized.

As described in function-style cast, the syntax T() (1) is prohibited if T names an array type, while T{} (5) is allowed.

All standard containers (std::vector, std::list, etc.) value-initialize their elements when constructed with a single size_type argument or when grown by a call to resize(), unless their allocator customizes the behavior of construct.

Example
Run this code
#include
#include
#include
#include

struct T1
{
int mem1;
std::string mem2;
virtual void foo() {} // make sure T1 is not an aggregate
}; // implicit default constructor

struct T2
{
int mem1;
std::string mem2;
T2(const T2&) {} // user-provided copy constructor
}; // no default constructor

struct T3
{
int mem1;
std::string mem2;
T3() {} // user-provided default constructor
};

std::string s{}; // class => default-initialization, the value is ""

int main()
{
int n{}; // scalar => zero-initialization, the value is 0
assert(n == 0);
double f = double(); // scalar => zero-initialization, the value is 0.0
assert(f == 0.0);
int* a = new int10; // array => value-initialization of each element
assert(a[9] == 0); // the value of each element is 0
T1 t1{}; // class with implicit default constructor =>
assert(t1.mem1 == 0); // t1.mem1 is zero-initialized, the value is 0
assert(t1.mem2 == ""); // t1.mem2 is default-initialized, the value is ""
// T2 t2{}; // error: class with no default constructor
T3 t3{}; // class with user-provided default constructor =>
std::cout << t3.mem1; // t3.mem1 is default-initialized to indeterminate value
assert(t3.mem2 == ""); // t3.mem2 is default-initialized, the value is ""
std::vector v(3); // value-initialization of each element
assert(v[2] == 0); // the value of each element is 0
std::cout << '\n';
delete[] a;
}
Possible output:

42
"""

flowcharts are generated:
"""
Start Value-Initialization
          |
          v
Is T a Class Type?
      /         \
    Yes          No
    |             |
Check if T's    Is T an Array Type?
Default Constructor?     /       \
    /       \            Yes        No
  User-     Not User        |          |
Provided?   Provided        |     Zero-Initialize
  |           |              |          the Object
  |           |              |
  |       Zero-Init +     Value-Initialize
  |       Default-Init    Each Array Element
  |
Default-Initialization Only
(No Zero-Initialization)
"""
"""
Start Value-Initialization
|
├── Is T a Class Type?
|     ├── Yes
|     |     ├── Is T's Default Constructor User-Provided?
|     |     |     ├── Yes
|     |     |     |     └── Perform Default-Initialization Only
|     |     |     └── No
|     |     |           └── Perform Zero-Initialization + Default-Initialization
|     |
|     └── No
|           ├── Is T an Array Type?
|           |     ├── Yes
|           |     |     └── Value-Initialize Each Array Element
|           |     └── No
|           |           └── Perform Zero-Initialization on the Object
|
End Value-Initialization
"""

however, these flow charts missed something important:
"""
In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate initialization is performed instead of value-initialization.

If T is a class type that has no default constructor but has a constructor taking std::initializer_list, list-initialization is performed.
"""

please amend the flowcharts