Copy constructors
복사 생성자는 동일한 클래스 타입의 인수로 호출될 수 있으며, 인수의 내용을 변경하지 않고 복사하는 생성자 입니다.
목차 |
구문
class-name
(
parameter-list
);
|
(1) | ||||||||
class-name
(
parameter-list
)
function-body
|
(2) | ||||||||
class-name
(
single-parameter-list
) = default;
|
(3) | (C++11부터) | |||||||
class-name
(
parameter-list
) = delete;
|
(4) | (C++11부터) | |||||||
class-name
::
class-name
(
parameter-list
)
function-body
|
(5) | ||||||||
class-name
::
class-name
(
single-parameter-list
) = default;
|
(6) | (C++11부터) | |||||||
| class-name | - | 복사 생성자가 선언되는 클래스 |
| parameter-list | - |
다음 모든 조건을 만족하는 비어 있지 않은
매개변수 목록
:
|
| single-parameter-list | - | 단일 매개변수만을 가지는 매개변수 목록 으로, 해당 매개변수는 T & , const T & , volatile T & 또는 const volatile T & 타입이며 기본 인수를 가지지 않음 |
| function-body | - | 복사 생성자의 함수 본문 |
설명
struct X { X(X& other); // 복사 생성자 // X(X other); // 오류: 잘못된 매개변수 타입 }; union Y { Y(Y& other, int num = 1); // 다중 매개변수를 가진 복사 생성자 // Y(Y& other, int num); // 오류: `num`에 기본 인자가 없음 };
복사 생성자는 객체가 동일한 타입의 다른 객체로부터 초기화 될 때마다 호출됩니다 ( 직접 초기화 또는 복사 초기화 ) (단, 오버로드 해결 이 더 나은 일치를 선택하거나 호출이 생략 되지 않는 경우). 여기에는 다음이 포함됩니다
-
초기화:
T a
=
b
;
또는
T a
(
b
)
;
, 여기서
b
는
T타입임; -
함수 인수 전달:
f
(
a
)
;
, 여기서
a
는
T타입이고 f 는 void f ( T t ) 임; -
함수 반환:
return
a
;
와 같은 함수 내부에서,
T f
(
)
, 여기서
a
는
T타입이며, move constructor 가 없음.
암시적으로 선언된 복사 생성자
클래스 타입에 대해 사용자 정의 복사 생성자가 제공되지 않으면, 컴파일러는 항상 복사 생성자를 비- explicit inline public 멤버로 선언합니다. 이 암시적으로 선언된 복사 생성자는 다음 형태를 가집니다: T :: T ( const T & ) 다음 조건들이 모두 참일 경우:
-
T의 각 직접 및 가상 기본 클래스
B는 매개변수 타입이 const B & 또는 const volatile B & 인 복사 생성자를 가져야 합니다; -
T의 클래스 타입 또는 클래스 타입 배열인 각 비정적 데이터 멤버
M은 매개변수 타입이 const M & 또는 const volatile M & 인 복사 생성자를 가져야 합니다.
그렇지 않으면, 암시적으로 선언된 복사 생성자는 T :: T ( T & ) 입니다.
이러한 규칙들 때문에, 암시적으로 선언된 복사 생성자는 volatile lvalue 인자에 바인딩할 수 없습니다.
클래스는 여러 개의 복사 생성자를 가질 수 있습니다. 예를 들어 T :: T ( const T & ) 와 T :: T ( T & ) 모두를 가질 수 있습니다.
|
일부 사용자 정의 복사 생성자가 존재하더라도, 사용자는 여전히 키워드 default 를 사용하여 암시적 복사 생성자 선언을 강제할 수 있습니다. |
(since C++11) |
암묵적으로 선언된(또는 첫 선언에서 기본 설정된) 복사 생성자는 다음과 같이 예외 명세를 가집니다. 동적 예외 명세 (C++17까지) noexcept 명세 (C++17부터) .
암시적으로 정의된 복사 생성자
암시적으로 선언된 복사 생성자가 삭제되지 않은 경우, 컴파일러에 의해 ODR-사용 되거나 상수 평가에 필요할 때 (C++11부터) 정의됩니다(즉, 함수 본문이 생성되고 컴파일됨). 공용체(union) 타입의 경우, 암시적으로 정의된 복사 생성자는 객체 표현을 복사합니다( std::memmove 에 의한 것처럼). 비공용체 클래스 타입의 경우, 이 생성자는 객체의 직접 기반 서브객체들과 멤버 서브객체들을 초기화 순서대로 직접 초기화를 사용하여 전체 멤버별 복사를 수행합니다. 참조 타입의 비정적 데이터 멤버 각각에 대해, 복사 생성자는 참조를 원본 참조가 바인딩된 동일한 객체나 함수에 바인딩합니다.
|
이것이 constexpr constructor (until C++23) constexpr function (since C++23) 의 요구사항을 만족할 경우, 생성된 복사 생성자는 constexpr 입니다.
|
(since C++11) |
삭제된 복사 생성자
암시적으로 선언된
또는 명시적으로 기본화된
(C++11부터)
클래스
T
의 복사 생성자는
정의되지 않음
(C++11 이전)
삭제된 것으로 정의됨
(C++11부터)
다음 조건 중 하나라도 만족되는 경우:
|
(since C++11) |
-
T가 클래스 타입M(또는 다차원 배열)의 잠재적으로 생성된 하위 객체 를 가지고 있어서
-
-
M의 소멸자가 삭제되었거나 삭제되었거나 (C++11부터) 복사 생성자에서 접근할 수 없거나, -
M의 복사 생성자를 찾기 위해 적용된 오버로드 해결이
-
- 사용 가능한 후보를 결과로 내지 않거나,
- 해당 하위 객체가 variant member 인 경우, trivial하지 않은 함수를 선택하는 경우.
-
|
암시적으로 선언된
|
(C++11부터) |
Trivial 복사 생성자
클래스
T
의 복사 생성자는 다음 조건이 모두 참일 때 trivial합니다:
- 사용자가 제공한 것이 아님(즉, 암시적으로 정의되었거나 기본값으로 설정됨);
-
T가 가상 멤버 함수를 가지지 않음; -
T가 가상 기본 클래스를 가지지 않음; -
T의 모든 직접 기본 클래스에 대해 선택된 복사 생성자가 trivial함; -
T의 모든 비정적 클래스 타입(또는 클래스 타입 배열) 멤버에 대해 선택된 복사 생성자가 trivial함;
비-공용체 클래스에 대한 사소한 복사 생성자는 인수의 모든 스칼라 하위 객체(재귀적으로, 하위 객체의 하위 객체 등 포함)를 효과적으로 복사하고 다른 동작을 수행하지 않습니다. 그러나 패딩 바이트는 복사할 필요가 없으며, 복사된 하위 객체의 객체 표현이 값이 동일하기만 하다면 원본과 반드시 같을 필요는 없습니다.
TriviallyCopyable 객체는 객체 표현을 수동으로 복사하여 복사할 수 있습니다, 예를 들어 std::memmove 를 사용하여. C 언어와 호환되는 모든 데이터 타입(POD 타입)은 trivially copyable입니다.
적격 복사 생성자
|
복사 생성자는 사용자 선언되었거나 암시적으로 선언되고 정의 가능한 경우 적격입니다. |
(until C++11) |
|
복사 생성자는 삭제되지 않은 경우 적격입니다. |
(since C++11)
(until C++20) |
|
복사 생성자는 다음 조건을 모두 만족하는 경우 적격입니다:
|
(since C++20) |
적격 복사 생성자의 triviality는 클래스가 implicit-lifetime type 인지 여부와 클래스가 trivially copyable type 인지 여부를 결정합니다.
참고 사항
많은 상황에서, 복사 생성자는 관찰 가능한 부수 효과를 발생시키더라도 최적화되어 제거됩니다. 자세한 내용은 copy elision 을 참조하십시오.
예제
struct A { int n; A(int n = 1) : n(n) {} A(const A& a) : n(a.n) {} // 사용자 정의 복사 생성자 }; struct B : A { // 암시적 기본 생성자 B::B() // 암시적 복사 생성자 B::B(const B&) }; struct C : B { C() : B() {} private: C(const C&); // 복사 불가, C++98 스타일 }; int main() { A a1(7); A a2(a1); // 복사 생성자 호출 B b; B b2 = b; A a3 = b; // A&로의 변환 및 복사 생성자 volatile A va(10); // A a4 = va; // 컴파일 오류 C c; // C c2 = c; // 컴파일 오류 }
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 1353 | C++98 |
암시적으로 선언된 복사 생성자가 정의되지 않는 조건에서
다차원 배열 타입을 고려하지 않음 |
이러한 타입들을 고려함 |
| CWG 2094 | C++11 | volatile 멤버들이 복사를 비트리비얼하게 만듦 ( CWG 이슈 496 ) | 트리비얼함에 영향 없음 |
| CWG 2171 | C++11 | X ( X & ) = default 가 비트리비얼했음 | 트리비얼하게 만듦 |
| CWG 2595 | C++20 |
더 제약된 다른 복사 생성자가 존재하지만
해당 연관 제약 조건을 만족하지 않는 경우 복사 생성자가 적격하지 않았음 |
이 경우 적격할 수 있음 |