2012-03-17 2 views
14

이 질문은 this answer에 의해 제기 된 문제에서 비롯됩니다.할당 연산자를 참조 대신 값으로 바꿈

보통 T 유형의 복사 할당 연산자를 T& operator=(const T&)으로 정의하고 T의 할당 연산자를 T& operator=(T&&)으로 옮깁니다.

그러나 참조가 아닌 값 매개 변수를 사용하면 어떻게됩니까?

class T 
{ 
public: 
    T& operator=(T t); 
}; 

이렇게하면 T가 복사 및 이동 가능하게 만들어야합니다. 그러나 내가 알고 싶은 것은 T의 언어 파급 효과는 무엇입니까?

구체적 : T위한 복사 할당 연산자 등이 계수는, 본 명세서에있어서

  1. 합니까?
  2. 이 계산서는 T에 대한 이동 지정 연산자입니까?
  3. T에는 컴파일러에서 생성 한 복사본 할당 연산자가 있습니까?
  4. T에는 컴파일러에서 생성 한 이동 지정 연산자가 있습니까?
  5. 이것은 어떻게 std::is_move_assignable과 같은 특성 클래스에 영향을 줍니까?
+0

관련 토론 : http://cpp-next.com/archive/2009/08/want-speed-pass-by-value – mavam

+0

Visual Studio와 g ++ 모두에서 컴파일러 오류가 발생합니다. T & operator = (T t)와 T & operator = (T && t)가 모호하기 때문에 – user929404

+0

@ user929404 : 당신이해야합니다. 요점은 * 두 값 모두를 * 값 할당으로 복사 및 이동 할당을 대체한다는 것입니다. –

답변

14

대부분이 §12.8에 설명되어 있습니다. 단락 (17)는 사용자가 선언 복사 대입 연산자로 계산을 정의 :

사용자 선언 복사 할당 연산자 X::operator= 유형 X, X&의 단 하나 개의 매개 변수를 사용하여 클래스 X의 비 정적 템플릿이 아닌 멤버 함수입니다, const X&, volatile X& 또는 const volatile X&입니다.

단락 (19)는 사용자가 선언 이동 할당 연산자로 계산을 정의 :

사용자 선언 이동 할당 연산자 X::operator= 정확히 하나 클래스 X의 비 정적 템플릿이 아닌 멤버 함수입니다 유형 X&&, const X&&, volatile X&& 또는 const volatile X&&의 매개 변수

따라서 복사 할당 연산자로 계산되지만 이동 할당 연산자는 계산되지 않습니다. 클래스 정의가 명시 적으로 사본 할당 운영자, 하나의 암시 적 선언을 선언하지 않는 경우

: 컴파일러가 복사 대입 연산자를 생성 할 때

단락 (18)는 말한다. 클래스 정의가 이동 생성자 또는 이동 대입 연산자를 선언하면 암시 적으로 선언 된 복사 대입 연산자가 삭제됨으로 정의됩니다. 그렇지 않으면 은 기본값 (8.4)으로 정의됩니다.후자의 경우는 클래스에 사용자 선언 복사 생성자 또는 사용자 선언 소멸자가있는 경우 사용되지 않습니다. 컴파일러는 대입 연산자를 이동 생성 할 때

단락 (20)는 이렇게 알려줍니다 경우 기본값으로

클래스 X의 정의가 명시 적으로 이동 할당 연산자를 선언하지 않는 경우, 하나는 암시 적으로 선언됩니다 그리고 경우에만
[...]
- X 사용자 선언 복사 할당 연산자를 가지고 있지 않습니다
[...]

클래스에 사용자가 선언 한 복사 할당 연산자가 있으므로 암시 적으로 할당 된 연산자가 컴파일러에서 생성되지 않습니다.

std::is_copy_assignablestd::is_move_assignable은 각각 is_assignable<T&,T const&>::valueis_assignable<T&,T&&>::value과 동일한 값을 갖는 것으로 표 49에 설명되어있다. 평가되지 않은 피연산자 (5 절)로 처리 할 때

발현 declval<T>() = declval<U>() 잘 형성된다 : 즉, 표 is_assignable<T,U>::valuetrue 것을 말해 준다. TU과 관련이없는 컨텍스트에서 액세스 확인은 으로 수행됩니다. 할당 표현식의 즉각적인 컨텍스트 인 의 유효성 만 고려됩니다. declval<T&>() = declval<T const&>()declval<T&>() = declval<T&&>() 모두 이후

해당 클래스에 대해 잘 형성되고, 여전히 할당 사본으로 간주하고 할당 이동합니다.

내가이 주석에 언급 한 것처럼, 이동 생성자가있는 경우 operator=이 이동을 올바르게 수행하지만 기술적으로 이동 할당 연산자로 계산되지 않는다는 점이 궁금합니다. 클래스에 복사 생성자가없는 경우에는 더 이상하지 않습니다. 복사를하지 않고 이동 만하는 복사 할당 연산자가 있습니다.

관련 문제