Namespaces
Variants

Copy-initialization

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

다른 객체로부터 객체를 초기화합니다.

목차

구문

T object = other ; (1)
T object = { other }; (2) (C++11 이전)
f ( other ) (3)
return other ; (4)
throw object ;

catch ( T object )

(5)
T array [ N ] = { other-sequence }; (6)

설명

복사 초기화는 다음과 같은 상황에서 수행됩니다:

1) 참조 타입이 아닌 T 타입의 명명된 변수(자동, 정적, 또는 스레드-로컬)가 등호 뒤에 표현식으로 구성된 초기화자와 함께 선언될 때.
2) (until C++11) 스칼라 타입 T 의 명명된 변수가 등호 뒤에 중괄호로 둘러싸인 표현식으로 구성된 초기화자와 함께 선언될 때 (참고: C++11부터는 이것이 목록 초기화 로 분류되며, 축소 변환은 허용되지 않음).
3) 함수에 인자를 값으로 전달 할 때.
4) 값을 반환하는 함수에서 반환 할 때.
5) throw 또는 catch 로 예외를 값으로 전달하거나 받을 때.
6) aggregate initialization 의 일부로서, 초기화자가 제공된 각 요소를 초기화하기 위해.

복사 초기화의 효과는 다음과 같습니다:

  • 첫째, T 가 클래스 타입이고 초기화자가 prvalue 표현식이며 그 cv-unqualified 타입이 T 와 동일한 클래스인 경우, 해당 초기화 표현식 자체가 (그로부터 구체화된 임시 객체가 아닌) 대상 객체를 초기화하는 데 사용됩니다: copy elision 을 참조하십시오.
(C++17부터)
  • 첫째 (C++17까지) 그렇지 않으면 (C++17부터) , 만약 T 가 클래스 타입이고 other 의 타입의 cv-unqualified 버전이 T 이거나 T 에서 파생된 클래스인 경우, T non-explicit 생성자들 을 검사하고 오버로드 해결을 통해 가장 적합한 매치를 선택합니다. 그런 다음 해당 생성자를 호출하여 객체를 초기화합니다.
  • 그렇지 않고, T 가 클래스 타입이며, other 의 타입의 cv-unqualified 버전이 T 가 아니거나 T 로부터 파생되지 않았거나, T 가 비클래스 타입이지만 other 의 타입이 클래스 타입인 경우, other 의 타입에서 T (또는 T 가 클래스 타입이고 변환 함수가 사용 가능한 경우 T 로부터 파생된 타입)로 변환할 수 있는 사용자 정의 변환 시퀀스 가 검사되고 오버로드 해결을 통해 최적의 시퀀스가 선택됩니다. 변환의 결과는 rvalue 임시 객체 (C++11까지) prvalue 임시 객체 (C++11부터) (C++17까지) prvalue 표현식 (C++17부터) 으로, 변환 생성자 가 사용된 경우 T 의 cv-unqualified 버전이며, 이 결과가 객체를 직접 초기화 하는 데 사용됩니다. 마지막 단계는 일반적으로 최적화되어 제거 되고 변환 결과가 대상 객체를 위해 할당된 메모리에 직접 생성되지만, 사용되지 않더라도 적절한 생성자(이동 또는 복사)가 접근 가능해야 합니다. (C++17까지)
  • 그렇지 않은 경우 (즉, T other 의 타입 모두 클래스 타입이 아닌 경우), 필요한 경우 표준 변환 을 사용하여 other 의 값을 T 의 cv-unqualified 버전으로 변환합니다.

참고 사항

복사 초기화(copy-initialization)는 직접 초기화(direct-initialization)보다 허용 범위가 제한적입니다: explicit 생성자 변환 생성자 가 아니며 복사 초기화 시에는 고려되지 않습니다.

struct Exp { explicit Exp(const char*) {} }; // const char*에서 변환 불가
Exp e1("abc");  // 정상
Exp e2 = "abc"; // 오류, 복사 초기화는 explicit 생성자를 고려하지 않음
struct Imp { Imp(const char*) {} }; // const char*에서 변환 가능
Imp i1("abc");  // 정상
Imp i2 = "abc"; // 정상

또한, 복사 초기화에서의 암시적 변환은 초기화자로부터 직접 T 를 생성해야 하는 반면, 예를 들어 직접 초기화는 초기화자로부터 T 의 생성자 인자로의 암시적 변환을 기대합니다.

struct S { S(std::string) {} }; // std::string에서 암시적으로 변환 가능
S s("abc");   // OK: const char[4]에서 std::string으로 변환
S s = "abc";  // 오류: const char[4]에서 S로 변환 불가
S s = "abc"s; // OK: std::string에서 S로 변환

만약 other 가 rvalue 표현식이라면, move constructor 가 오버로드 해결에 의해 선택되어 복사 초기화 중에 호출됩니다. 이것은 여전히 복사 초기화로 간주됩니다; 이 경우를 위한 특별한 용어(예: 이동 초기화)는 없습니다.

암시적 변환 은 복사 초기화를 기준으로 정의됩니다: T 타입의 객체가 표현식 E 로 복사 초기화될 수 있다면, E T 로 암시적으로 변환 가능합니다.

등호 기호, = 는 명명된 변수의 복사 초기화에서 할당 연산자와 관련이 없습니다. 할당 연산자 오버로드는 복사 초기화에 아무런 영향을 미치지 않습니다.

예제

#include <memory>
#include <string>
#include <utility>
struct A
{
    operator int() { return 12;}
};
struct B
{
    B(int) {}
};
int main()
{
    std::string s = "test";        // OK: 생성자가 non-explicit임
    std::string s2 = std::move(s); // 이 복사 초기화는 이동을 수행함
//  std::unique_ptr<int> p = new int(1); // 오류: 생성자가 explicit임
    std::unique_ptr<int> p(new int(1));  // OK: 직접 초기화
    int n = 3.14;    // 부동소수점-정수 변환
    const int b = n; // const는 중요하지 않음
    int c = b;       // ...어떤 방식으로든
    A a;
    B b0 = 12;
//  B b1 = a;       // < 오류: 'A'에서 비스칼라 타입 'B'로의 변환 요청
    B b2{a};        // < 동일, A::operator int() 호출 후 B::B(int) 호출
    B b3 = {a};     // <
    auto b4 = B{a}; // <
//  b0 = a;         // < 오류, 대입 연산자 오버로드 필요
    [](...){}(c, b0, b3, b4); // 이 변수들이 사용되었다고 가정
}

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
CWG 5 C++98 대상 타입의 cv 한정자가 변환 생성자에 의해 초기화된
임시 객체에 적용됨
임시 객체는 cv 한정되지 않음
CWG 177 C++98 클래스 객체의 복사 초기화 과정에서 생성된 임시 객체의
값 카테고리가 명시되지 않음
rvalue로 명시됨

참고 항목