Copy-initialization - cppreference.com (original) (raw)

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) (5)
T array[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.

  2. (until C++11) 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).

  3. When returning from a function that returns by value.

  4. As part of aggregate initialization, to initialize each element for which an initializer is provided.

The effects of copy-initialization are:

First, if 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. (since C++17)

[edit] Notes

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.

[edit] Example

#include #include #include   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 p = new int(1); // error: constructor is explicit std::unique_ptr 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 tothe temporary initialized by a converting constructor the temporary is not cv-qualified
CWG 177 C++98 the value category of the temporary created duringcopy-initialization of a class object is unspecified specified as rvalue

[edit] See also