Initializes an object from another object.
[edit] Syntax T object=
other;
(1) T object =
{
other};
(2) (until C++11) f(
other)
(3) return
other;
(4) throw
object;
catch (
T object)
[
N] = {
other-sequence};
(6) [edit] Explanation
Copy-initialization is performed in the following situations:
1) When a named variable (automatic, static, or thread-local) of a non-reference type T
is declared with the initializer consisting of an equals sign followed by an expression.
When a named variable of a scalar type
T
is declared with the initializer consisting of an equals sign followed by a brace-enclosed expression (Note: as of C++11, this is classified as
list initialization, and narrowing conversion is not allowed).
4)When
returningfrom a function that returns by value.
The effects of copy-initialization are:
T
is a class type and the initializer is a prvalue expression whose cv-unqualified type is the same class as T
, the initializer expression itself, rather than a temporary materialized from it, is used to initialize the destination object: see copy elision.T
is a class type and the cv-unqualified version of the type of other is T
or a class derived from T
, the non-explicit constructors of T
are examined and the best match is selected by overload resolution. That constructor is then called to initialize the object.T
is a class type, and the cv-unqualified version of the type of other is not T
or derived from T
, or if T
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 to 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 rvalue temporary(until C++11)prvalue temporary(since C++11)(until C++17)prvalue expression(since C++17) of the cv-unqualified version of T
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.(until C++17)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 of T
.Copy-initialization is less permissive than direct-initialization: explicit constructors are not converting constructors and are not considered for copy-initialization.
struct Exp { explicit Exp(const char*) {} }; // not convertible from const char* Exp e1("abc"); // OK Exp e2 = "abc"; // Error, copy-initialization does not consider explicit constructor struct Imp { Imp(const char*) {} }; // convertible from const char* Imp i1("abc"); // OK Imp i2 = "abc"; // OK
In addition, the implicit conversion in copy-initialization must produce T
directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T
's constructor.
struct S { S(std::string) {} }; // implicitly convertible from std::string S s("abc"); // OK: conversion from const char[4] to std::string S s = "abc"; // Error: no conversion from const char[4] to S S s = "abc"s; // OK: conversion from std::string to S
If other is an rvalue expression, a move constructor will be selected by overload resolution and called during copy-initialization. This is still considered copy-initialization; there is no special term (e.g., move-initialization) for this case.
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.
#include <memory> #include <string> #include <utility> struct A { operator int() { return 12;} }; struct B { B(int) {} }; 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 A a; B b0 = 12; // B b1 = a; // < error: conversion from 'A' to non-scalar type 'B' requested B b2{a}; // < identical, calling A::operator int(), then B::B(int) B b3 = {a}; // < auto b4 = B{a}; // < // b0 = a; // < error, assignment operator overload needed [](...){}(c, b0, b3, b4); // pretend these variables are used }[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior CWG 5 C++98 the cv-qualification of the destination type is applied toexplicit
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