Difference between revisions of "cpp/language/copy initialization"
("explicit" constructors are not candidates for copy-initialization) |
m (some wikilinks) |
||
Line 18: | Line 18: | ||
Copy initialization is performed in the following situations: | Copy initialization is performed in the following situations: | ||
@1@ when a named variable (automatic, static, or thread-local) of a non-reference type {{tt|T}} is declared with the initializer consisting of an equals sign followed by an expression. | @1@ when a named variable (automatic, static, or thread-local) of a non-reference type {{tt|T}} is declared with the initializer consisting of an equals sign followed by an expression. | ||
− | @2@ when passing an argument to a function by value | + | @2@ when {{rlp|operator_other#Built-in_function_call_operator|passing an argument}} to a function by value |
− | @3@ when returning from a function that returns by value | + | @3@ when {{rlp|return|returning}} from a function that returns by value |
− | @4@ when throwing or catching an exception by value | + | @4@ when {{rlp|throw|throwing}} or {{rlp|try catch|catching}} an exception by value |
− | @5@ as part of | + | @5@ as part of {{rlp|aggregate_initialization|aggregate initialization}}, to initialize each element for which an initializer is provided |
The effects of copy initialization are: | The effects of copy initialization are: | ||
− | * If {{tt|T}} is a class type and the type of {{spar|other}} is cv-unqualified version of {{tt|T}} or a class derived from {{tt|T}}, the converting | + | * If {{tt|T}} is a class type and the type of {{spar|other}} is cv-unqualified version of {{tt|T}} or a class derived from {{tt|T}}, the {{rlp|converting constructor}}s of {{tt|T}} are examined and the best match is selected by overload resolution. The constructor is then called to initialize the object. |
* If {{tt|T}} is a class type, and the type of {{spar|other}} is different, or if {{tt|T}} is non-class type, but the type of {{spar|other}} is a class type, [[cpp/language/implicit_cast|user-defined conversion sequences]] that can convert from the type of {{spar|other}} to {{tt|T}} (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution. The result of the conversion, which is a prvalue temporary if a {{rlp|converting constructor}} was used, is then used to [[cpp/language/direct_initialization|direct-initialize]] the object. The last step is usually [[cpp/language/copy_elision|optimized out]] and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. | * If {{tt|T}} is a class type, and the type of {{spar|other}} is different, or if {{tt|T}} is non-class type, but the type of {{spar|other}} is a class type, [[cpp/language/implicit_cast|user-defined conversion sequences]] that can convert from the type of {{spar|other}} to {{tt|T}} (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution. The result of the conversion, which is a prvalue temporary if a {{rlp|converting constructor}} was used, is then used to [[cpp/language/direct_initialization|direct-initialize]] the object. The last step is usually [[cpp/language/copy_elision|optimized out]] and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. | ||
Line 32: | Line 32: | ||
===Notes=== | ===Notes=== | ||
− | Copy-initialization is less permissive than direct-initialization: explicit constructors are not converting | + | Copy-initialization is less permissive than direct-initialization: {{rlp|explicit|explicit constructors}} are not {{rlp|converting constructor}}s and are not considered for copy-initialization. |
If {{spar|other}} is an rvalue expression, [[cpp/language/move_constructor|move constructor]] will be selected by overload resolution and called during copy-initialization. There is no such term as move-initialization. | If {{spar|other}} is an rvalue expression, [[cpp/language/move_constructor|move constructor]] will be selected by overload resolution and called during copy-initialization. There is no such term as move-initialization. |
Revision as of 08:15, 26 February 2015
Initializes an object from another object
Contents |
Syntax
T object = other;
|
(1) | ||||||||
f( other)
|
(2) | ||||||||
return other;
|
(3) | ||||||||
throw object;
|
(4) | ||||||||
T array[ N] = { other};
|
(5) | ||||||||
Explanation
Copy initialization is performed in the following situations:
T
is declared with the initializer consisting of an equals sign followed by an expression.The effects of copy initialization are:
- If
T
is a class type and the type of other is cv-unqualified version ofT
or a class derived fromT
, the converting constructors ofT
are examined and the best match is selected by overload resolution. The constructor is then called to initialize the object.
- If
T
is a class type, and the type of other is different, or ifT
is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other toT
(or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution. The result of the conversion, which is a prvalue temporary if a converting constructor was used, is then used to direct-initialize the object. The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used.
- Otherwise (if neither
T
nor the type of other are class types), standard conversions are used, if necessary, to convert the value of other to the cv-unqualified version ofT
.
Notes
Copy-initialization is less permissive than direct-initialization: explicit constructors are not converting constructors and are not considered for copy-initialization.
If other is an rvalue expression, move constructor will be selected by overload resolution and called during copy-initialization. There is no such term as move-initialization.
Implicit conversion is defined in terms of copy-initialization: if an object of type T
can be copy-initialized with expression E
, then E
is implicitly convertible to T
.
The equals sign, =
, in copy-initialization of a named variable is not related to the assignment operator. Assignment operator overloads have no effect on copy-initialization.
Example
#include <string> #include <utility> #include <memory> int main() { std::string s = "test"; // OK: constructor is non-explicit std::string s2 = std::move(s); // this copy-initialization performs a move // std::unique_ptr<int> p = new int(1); // error: constructor is explicit std::unique_ptr<int> p(new int(1)); // OK: direct-initialization int n = 3.14; // floating-integral conversion const int b = n; // const doesn't matter int c = b; // ...either way }