Initializes an object from explicit set of constructor arguments.
[edit] Syntax T object(
arg );
T object (
arg1, arg2, ... );
{
arg };
(2) (since C++11) T (
other )
T (
arg1, arg2, ... )
static_cast<
T >(
other )
(4) new
T(
args, ... )
(5) Class::
Class()
:
member(
args, ... )
{
... }
(6) [
arg]() {
... }
(7) (since C++11) [edit] Explanation
Direct-initialization is performed in the following situations:
1) Initialization with a nonempty parenthesized list of expressions or braced-init-lists(since C++11).
2)Initialization of an object of non-class type with a single brace-enclosed initializer
(note: for class types and other uses of braced-init-list, see list-initialization)(since C++11).
3)Initialization of
a prvalue temporary(until C++17)the result object of a prvalue(since C++17)by
function-style castor with a parenthesized expression list.
4)Initialization of
a prvalue temporary(until C++17)the result object of a prvalue(since C++17)by a
static_castexpression.
5) Initialization of an object with dynamic storage duration by a new-expression with an initializer.
6)Initialization of a base or a non-static member by constructor
initializer list.
7) Initialization of closure object members from the variables caught by copy in a lambda-expression.
The effects of direct-initialization are:
T
is an array type,struct A { explicit A(int i = 0) {} }; A a[2](A(1)); // OK: initializes a[0] with A(1) and a[1] with A() A b[2]{A(1)}; // error: implicit copy-list-initialization of b[1] // from {} selected explicit constructor(since C++20)
T
is a class type,T
(ignoring cv-qualification), the initializer expression itself, rather than a temporary materialized from it, is used to initialize the destination object.T
are examined and the best match is selected by overload resolution. The constructor is then called to initialize the object.struct B { int a; int&& r; }; int f(); int n = 10; B b1{1, f()}; // OK, lifetime is extended B b2(1, f()); // well-formed, but dangling reference B b3{1.0, 1}; // error: narrowing conversion B b4(1.0, 1); // well-formed, but dangling reference B b5(1.0, std::move(n)); // OK(since C++20)
T
is a non-class type but the source type is a class type, the conversion functions of the source type and its base classes, if any, are examined and the best match is selected by overload resolution. The selected user-defined conversion is then used to convert the initializer expression into the object being initialized.T
is bool and the source type is std::nullptr_t, the value of the initialized object is false.T
, and the initial value of the object being initialized is the (possibly converted) value.Direct-initialization is more permissive than copy-initialization: copy-initialization only considers non-explicit constructors and non-explicit user-defined conversion functions, while direct-initialization considers all constructors and all user-defined conversion functions.
In case of ambiguity between a variable declaration using the direct-initialization syntax (1) (with round parentheses) and a function declaration, the compiler always chooses function declaration. This disambiguation rule is sometimes counter-intuitive and has been called the most vexing parse.
#include <fstream> #include <iterator> #include <string> int main() { std::ifstream file("data.txt"); // The following is a function declaration: std::string foo1(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()); // It declares a function called foo1, whose return type is std::string, // first parameter has type std::istreambuf_iterator<char> and the name "file", // second parameter has no name and has type std::istreambuf_iterator<char>(), // which is rewritten to function pointer type std::istreambuf_iterator<char>(*)() // Pre-C++11 fix (to declare a variable) - add extra parentheses around one // of the arguments: std::string str1((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); // Post-C++11 fix (to declare a variable) - use list-initialization for any // of the arguments: std::string str2(std::istreambuf_iterator<char>{file}, {}); }[edit] Example
#include <iostream> #include <memory> #include <string> struct Foo { int mem; explicit Foo(int n) : mem(n) {} }; int main() { std::string s1("test"); // constructor from const char* std::string s2(10, 'a'); std::unique_ptr<int> p(new int(1)); // OK: explicit constructors allowed // std::unique_ptr<int> p = new int(1); // error: constructor is explicit Foo f(2); // f is direct-initialized: // constructor parameter n is copy-initialized from the rvalue 2 // f.mem is direct-initialized from the parameter n // Foo f2 = 2; // error: constructor is explicit std::cout << s1 << ' ' << s2 << ' ' << *p << ' ' << f.mem << '\n'; }
Output:
[edit] See alsoexplicit
new
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4