Copy assignment operator
복사 할당 연산자는 동일한 클래스 타입의 인수로 호출될 수 있으며 인수의 내용을 변경하지 않고 복사하는, 비정적 멤버 함수 인 operator = 이름을 가진 비템플릿 함수입니다.
목차 |
구문
공식 복사 할당 연산자 구문에 대해서는 함수 선언 을 참조하십시오. 아래 구문 목록은 유효한 복사 할당 연산자 구문들의 전체 중 일부만 보여줍니다.
return-type
operator=(
parameter-list
);
|
(1) | ||||||||
return-type
operator=(
parameter-list
)
function-body
|
(2) | ||||||||
return-type
operator=(
parameter-list-no-default
) = default;
|
(3) | (C++11부터) | |||||||
return-type
operator=(
parameter-list
) = delete;
|
(4) | (C++11부터) | |||||||
return-type
class-name
::
operator=(
parameter-list
)
function-body
|
(5) | ||||||||
return-type
class-name
::
operator=(
parameter-list-no-default
) = default;
|
(6) | (C++11부터) | |||||||
| class-name | - |
복사 할당 연산자가 선언되는 클래스, 아래 설명에서 클래스 타입은
T
로 주어짐
|
| parameter-list | - |
T
,
T&
,
const
T
&
,
volatile
T
&
또는
const
volatile
T
&
타입의 단일 매개변수만을 갖는
매개변수 목록
|
| parameter-list-no-default | - |
T
,
T&
,
const
T
&
,
volatile
T
&
또는
const
volatile
T
&
타입의 단일 매개변수만을 가지며 기본 인수가 없는
매개변수 목록
|
| function-body | - | 복사 할당 연산자의 함수 본문 |
| return-type | - |
모든 타입이 가능하지만, 할당 연쇄를 허용하기 위해
T&
가 선호됨
|
설명
struct X { X& operator=(X& other); // 복사 할당 연산자 X operator=(X other); // 값에 의한 전달이 허용됨 // X operator=(const X other); // 오류: 잘못된 매개변수 타입 }; union Y { // 복사 할당 연산자는 위에 나열된 구문 외에도, // 일반 함수 선언 구문을 따르고 // 위에 나열된 제한 사항을 위반하지 않는 한 다양한 구문을 가질 수 있음 auto operator=(Y& other) -> Y&; // OK: 후행 반환 타입 Y& operator=(this Y& self, Y& other); // OK: 명시적 객체 매개변수 // Y& operator=(Y&, int num = 1); // 오류: 다른 비객체 매개변수를 가짐 };
복사 할당 연산자는 오버로드 해결 에 의해 선택될 때마다 호출됩니다. 예를 들어, 객체가 할당 표현식의 좌측에 나타날 때 호출됩니다.
암시적으로 선언된 복사 할당 연산자
사용자 정의 복사 할당 연산자가 클래스 타입에 대해 제공되지 않으면, 컴파일러는 항상 이를 inline public 멤버로 선언합니다. 이 암시적으로 선언된 복사 할당 연산자는 다음 조건이 모두 참일 때 T & T :: operator = ( const T & ) 형태를 가집니다:
-
T의 각 직접 기본 클래스
B는 매개변수가B또는 const B & 또는 const volatile B & 인 복사 할당 연산자를 가집니다; -
T의 클래스 타입 또는 클래스 타입 배열인 각 비정적 데이터 멤버
M은 매개변수가M또는 const M & 또는 const volatile M & 인 복사 할당 연산자를 가집니다.
그렇지 않으면 암시적으로 선언된 복사 할당 연산자는 T & T :: operator = ( T & ) 로 선언됩니다.
이러한 규칙들 때문에, 암시적으로 선언된 복사 할당 연산자는 volatile lvalue 인자에 바인딩할 수 없습니다.
클래스는 여러 개의 복사 할당 연산자를 가질 수 있습니다. 예를 들어 T & T :: operator = ( T & ) 와 T & T :: operator = ( T ) 를 모두 가질 수 있습니다. 사용자 정의 복사 할당 연산자가 존재하는 경우에도, 사용자는 default 키워드를 사용하여 암시적으로 선언된 복사 할당 연산자의 생성을 강제할 수 있습니다. (C++11부터)
암묵적으로 선언된(또는 첫 선언에서 기본 설정된) 복사 할당 연산자의 예외 명세는 다음과 같이 설명됩니다. 동적 예외 명세 (C++17까지) noexcept 명세 (C++17 이후)
복사 할당 연산자는 모든 클래스에 대해 항상 선언되므로, 기본 클래스의 할당 연산자는 항상 가려집니다. 만약 using-declaration 을 사용하여 기본 클래스의 할당 연산자를 가져오고, 해당 연산자의 인자 타입이 파생 클래스의 암시적 할당 연산자 인자 타입과 동일할 수 있다면, using-declaration도 암시적 선언에 의해 가려집니다.
암시적으로 정의된 복사 할당 연산자
암시적으로 선언된 복사 할당 연산자가 삭제되지도 않고 trivial하지도 않다면, 컴파일러에 의해 정의됩니다(즉, 함수 본문이 생성되고 컴파일됨). 이는 odr-used 되거나 needed for constant evaluation (C++14부터) 인 경우에 해당합니다. union 타입의 경우, 암시적으로 정의된 복사 할당은 객체 표현을 복사합니다( std::memmove 에 의한 것처럼). 비-union 클래스 타입의 경우, 이 연산자는 객체의 직접 기반 클래스와 비정적 데이터 멤버에 대해 초기화 순서대로 멤버별 복사 할당을 수행하며, 스칼라 타입에는 내장 할당을, 배열에는 멤버별 복사 할당을, 클래스 타입에는 복사 할당 연산자(비가상으로 호출됨)를 사용합니다.
|
클래스
|
(C++14부터)
(C++23 이전) |
|
클래스
|
(C++23부터) |
|
|
(since C++11) |
삭제된 복사 할당 연산자
암시적으로 선언된
또는 명시적으로 기본화된
(C++11부터)
복사 할당 연산자는 클래스
T
에 대해 다음 조건 중 하나라도 만족될 경우
정의되지 않으며
(C++11 이전)
삭제된 것으로 정의됩니다
(C++11부터)
:
-
T가 const 한정된 비클래스 타입(또는 다차원 배열)의 비정적 데이터 멤버를 가지고 있는 경우 -
T가 참조 타입의 비정적 데이터 멤버를 가지고 있는 경우 -
T가 클래스 타입M(또는 다차원 배열)의 잠재적으로 생성되는 하위 객체 를 가지고 있어,M의 복사 할당 연산자를 찾기 위한 오버로드 해결이 적용되는 경우
-
- 사용 가능한 후보를 생성하지 않거나,
- 하위 객체가 variant member 인 경우, non-trivial 함수를 선택하는 경우.
|
암시적으로 선언된 복사 할당 연산자는 클래스
|
(since C++11) |
Trivial 복사 할당 연산자
클래스
T
의 복사 할당 연산자는 다음 조건이 모두 참일 경우 trivial합니다:
- 사용자가 제공한 것이 아님(즉, 암시적으로 정의되었거나 기본값으로 설정됨);
-
T가 가상 멤버 함수를 가지지 않음; -
T가 가상 기본 클래스를 가지지 않음; -
T의 모든 직접 기본 클래스에 대해 선택된 복사 할당 연산자가 trivial함; -
T의 모든 비정적 클래스 타입(또는 클래스 타입의 배열) 멤버에 대해 선택된 복사 할당 연산자가 trivial함.
사소한 복사 할당 연산자는 객체 표현을 std::memmove 를 사용하는 것처럼 복사합니다. C 언어와 호환되는 모든 데이터 타입(POD 타입)은 사소하게 복사 할당 가능합니다.
적격 복사 할당 연산자
|
복사 할당 연산자는 사용자 선언되었거나 암시적으로 선언되고 정의 가능한 경우 적격입니다. |
(until C++11) |
|
복사 할당 연산자는 삭제되지 않은 경우 적격입니다. |
(since C++11)
(until C++20) |
|
복사 할당 연산자는 다음 모든 조건을 만족할 경우 적격입니다: |
(since C++20) |
적격 복사 할당 연산자의 triviality는 클래스가 trivially copyable type 인지 여부를 결정합니다.
참고 사항
복사 할당 연산자와 이동 할당 연산자가 모두 제공되는 경우, 인수가 rvalue (이름 없는 임시 객체와 같은 prvalue 또는 xvalue (예: std::move 의 결과))일 때 오버로드 해결은 이동 할당을 선택하고, 인수가 lvalue (이름 있는 객체 또는 lvalue 참조를 반환하는 함수/연산자)일 때는 복사 할당을 선택합니다. 복사 할당만 제공되는 경우, 모든 인수 범주가 이를 선택합니다(인수를 값으로 받거나 const 참조로 받는 한, rvalue가 const 참조에 바인딩될 수 있으므로). 이는 이동을 사용할 수 없을 때 복사 할당이 이동 할당의 대체 수단이 되도록 합니다.
상속 구조에서 여러 경로를 통해 접근 가능한 가상 기본 클래스 서브오브젝트가 암시적으로 정의된 복사 할당 연산자에 의해 여러 번 할당되는지 여부는 명시되지 않습니다(동일한 내용이 이동 할당 에도 적용됩니다).
자세한 내용은 사용자 정의 복사 할당 연산자의 예상 동작에 대한 추가 정보를 확인하려면 assignment operator overloading 를 참조하십시오.
예제
#include <algorithm> #include <iostream> #include <memory> #include <string> struct A { int n; std::string s1; A() = default; A(A const&) = default; // 사용자 정의 복사 할당 (copy-and-swap 관용구) A& operator=(A other) { std::cout << "copy assignment of A\n"; std::swap(n, other.n); std::swap(s1, other.s1); return *this; } }; struct B : A { std::string s2; // 암시적으로 정의된 복사 할당 }; struct C { std::unique_ptr<int[]> data; std::size_t size; // 사용자 정의 복사 할당 (copy-and-swap 관용구 아님) // 참고: copy-and-swap은 항상 자원을 재할당함 C& operator=(const C& other) { if (this != &other) // 자기 할당이 아닌 경우 { if (size != other.size) // 자원을 재사용할 수 없는 경우 { data.reset(new int[other.size]); size = other.size; } std::copy(&other.data[0], &other.data[0] + size, &data[0]); } return *this; } }; int main() { A a1, a2; std::cout << "a1 = a2 calls "; a1 = a2; // 사용자 정의 복사 할당 B b1, b2; b2.s1 = "foo"; b2.s2 = "bar"; std::cout << "b1 = b2 calls "; b1 = b2; // 암시적으로 정의된 복사 할당 std::cout << "b1.s1 = " << b1.s1 << "; b1.s2 = " << b1.s2 << '\n'; }
출력:
a1 = a2 calls copy assignment of A b1 = b2 calls copy assignment of A b1.s1 = foo; b1.s2 = bar
결함 보고서
다음 동작 변경 결함 보고서는 이전에 게시된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 1353 | C++98 |
암시적으로 선언된 복사 할당 연산자가 정의되지 않는 조건에서
다차원 배열 타입을 고려하지 않음 |
이러한 타입을 고려함 |
| CWG 2094 | C++11 |
volatile 서브오브젝트가 기본 제공 복사 할당 연산자를
비트리비얼하게 만듦 ( CWG 이슈 496 ) |
트리비얼리티에 영향 없음 |
| CWG 2171 | C++11 | operator = ( X & ) = default 가 비트리비얼했음 | 트리비얼하게 만듦 |
| CWG 2180 | C++11 |
클래스
T
의 기본 제공 복사 할당 연산자가
T
가 추상 클래스이고 복사 할당 불가능한 직접 가상 기본 클래스를
가질 경우 삭제된 것으로 정의되지 않았음 |
이 경우 연산자가
삭제된 것으로 정의됨 |
| CWG 2595 | C++20 |
더 제약된 복사 할당 연산자가 존재하지만 해당 연관 제약을
만족하지 못할 경우 복사 할당 연산자가 적격하지 않았음 |
이 경우에도
적격할 수 있음 |