복사 생성자복사 생성자 및 C++에서 연산자 오버로드 : 일반적인 함수가 가능합니까?
이후MyClass(const MyClass&);
및 = 연산자 과부하
MyClass& operator = (const MyClass&);
거의 동일한 코드, 동일한 매개 변수를 가지며 반환에서만 차이가 있지만 공통 함수를 가질 수 있습니까? 둘 다 사용하기 위해서?
복사 생성자복사 생성자 및 C++에서 연산자 오버로드 : 일반적인 함수가 가능합니까?
이후MyClass(const MyClass&);
및 = 연산자 과부하
MyClass& operator = (const MyClass&);
거의 동일한 코드, 동일한 매개 변수를 가지며 반환에서만 차이가 있지만 공통 함수를 가질 수 있습니까? 둘 다 사용하기 위해서?
예. 두 가지 공통된 옵션이 있습니다. 그것은 이전의 상태와 문제 자체에서 발생하는 처리에 관해서 도전을 좋은 operator=
되어 제공하지만
MyClass(const MyClass& other)
{
operator=(other);
}
: 하나는 - - 내가 추천하지 않는 명시 적으로 복사 생성자에서 operator=
를 호출하는 것입니다 할당. 또한 모든 구성원과 기지는 other
에 할당 될지라도 처음부터 기본값이 초기화됩니다. 이것은 심지어 모든 회원과 기지에 유효하지 않을 수도 있으며 그것이 유효한 곳이라 할지라도 의미 상으로 중복되어 실질적으로 비쌀 수도 있습니다.
복제 생성자와 스왑 메서드를 사용하여 operator=
을 구현하는 것이 점차 보편화되고 있습니다.
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
swap(tmp);
return *this;
}
또는 :
MyClass& operator=(MyClass other)
{
swap(other);
return *this;
}
swap
함수가 단지 내부의 소유권을 바꿉니다 기존 상태를 정리하거나 새로운 자원을 할당 할 필요가 없기 때문에 작성하는 일반적으로 간단하다.
복사 및 스왑 이디엄의 장점은 자동으로 자체 할당 안전하고 스왑 작업이 노 쓰 로우가 아니라면 매우 예외적 인 안전하다는 것입니다.
강하게 예외적 인 경우를 제외하면 '손'으로 쓰여진 할당 연산자는 대개 배정 된 사람의 이전 자원을 할당 해제하기 전에 새 자원의 복사본을 할당해야합니다. 따라서 예외가 발생하면 새 자원을 할당 할 수 있습니다. 여전히 반환됩니다. 이 모든 것은 카피 앤 스왑 (copy-and-swap)과 함께 무료로 제공되지만 일반적으로 더 복잡하기 때문에 처음부터 오류가 발생하기 쉽습니다.
주의해야 할 점은 스왑 메서드가 실제 스왑이며 복사 생성자와 할당 연산자 자체를 사용하는 기본값 인 std::swap
이 아닌지 확인하는 것입니다.
일반적으로 구성원별로 swap
이 사용됩니다. std::swap
이 작동하며 모든 기본 유형 및 포인터 유형에 '노 스로우'가 보장됩니다. 대부분의 스마트 포인터는 노 쓰루 (no-throw) 보장으로 바꿀 수 있습니다.
실제로, 그들은 일반적인 작업이 아닙니다. 복사본 매개 변수가 처음으로 개체의 멤버를 초기화하는 동안 할당 연산자는 기존 값을 재정의합니다. 이것을 고려해 볼 때, copy ctor로부터'operator ='를 alling하는 것은 사실 아주 나쁜 것입니다. 왜냐하면 처음에 모든 값을 어떤 기본값으로 초기화하기 때문에 다른 객체의 값으로 바로 덮어 쓰기 때문입니다. – sbi
나는 공통 옵션을 말했고 조작은하지 않았다. 나는 복사 생성자로부터'operator ='를 호출하는 것이 좋지 않다는 것에 완전히 동의하지만, 실제 코드가 얼마나 흔한 지 알기 위해서는 실제 코드를 합리적으로 살펴 봐야한다. –
Downvoters, 설명해 주시겠습니까? –
복사 생성자는 원시 메모리였던 객체의 최초 초기화를 수행합니다. 대입 연산자 OTOH는 기존 값을 새로운 값으로 대체합니다. 자주 사용하지 않는 것보다 오래된 리소스 (예 : 메모리)를 해제하고 새 리소스를 할당하는 작업이 포함됩니다.
둘 사이에 유사성이있는 경우 할당 연산자가 파괴 및 복사 생성을 수행한다는 것입니다. 일부 개발자는 실제로 위치 결정 파괴 (place-in-place destruction)와 배치 복사 - 건설 (place-copy-construction)에 의한 할당을 실제로 사용했습니다. 그러나 이것은 매우 나쁜 아이디어입니다.(어떤이 경우하면 파생 클래스의 할당시라는 기본 클래스의 대입 연산자입니까?) 일반적으로 요즘 찰스으로 swap
을 사용하는 표준 관용구 간주 무엇
제안 :
는MyClass& operator=(MyClass other)
{
swap(other);
return *this;
}
이 복사본을 사용 -construction (참고로 other
이 복사 됨) 및 파괴 (함수의 끝에서 파괴 됨) - 올바른 순서로 사용됩니다. 파괴 (파괴하지 말아야 함) 이전에 건설 (실패 할 수도 있음). 내 마음이 "복사"를 생각하고 내 상식을 자극 할 때 단어 "스왑"을 읽어,
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
swap(tmp);
return *this;
}
첫째 :
뭔가에 대해 날 귀찮게. 또한, 나는이 공상 속임수의 목표에 의문을 제기한다. 예, 스왑 이전에 새로운 (복사 된) 리소스를 구성 할 때 예외가 발생해야합니다. 스왑은 모든 새 데이터가 채워지기 전에 안전하게 채워지는 것처럼 보입니다.
괜찮습니다. 그렇다면 스왑 이후 발생한 예외는 무엇입니까? (임시 객체가 범위를 벗어날 때 이전 리소스가 소멸되는 경우) 할당의 사용자 관점에서 볼 때 작업은 실패했습니다. 거대한 부작용이 있습니다. 복사가 실제로 발생했습니다. 실패한 자원 정리 만있었습니다. 외부에서 작업이 실패한 것 같아도 대상 객체의 상태가 변경되었습니다.
그래서, 내가 대신 더 자연스러운 "전송"할 "스왑"의 제안 :
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
transfer(tmp);
return *this;
}
이 임시 객체의 구조가 여전히 있지만, 다음 즉각적인 조치가 모두 현재의 자원을 확보하는 것입니다 목적지는 이동하기 전에 (그리고 NULL을 두 번 해제하지 않기 때문에) 소스의 자원을 이동시킵니다.
대신에 {construct, move, destruct} 대신 {construct, destruct, move}를 제안합니다. 가장 위험한 행동 인이 조치는 다른 모든 조치가 끝난 후 마지막으로 취해진 조치입니다.
예, 두 스키마 모두에서 삭제가 실패합니다. 데이터가 손상되었거나 (생각하지 않았을 때 복사) 또는 손실되었습니다 (생각하지 않았을 때 해제 됨). 잃어버린 것이 손상된 것보다 낫습니다. 데이터가 불량 데이터보다 우수합니다.
스왑 대신 전송. 어쨌든 그것은 제 제안입니다.
소멸자가 실패해서는 안되기 때문에 소멸시 예외는 예상되지 않습니다. 그리고 이동이 가장 위험한 작업 인 경우 파괴 뒤에서 이동을 움직이는 이점은 없을 것입니다. 즉, 표준 구성표에서 이동 실패는 이전 상태를 손상시키지 않지만 새 구성표는 손상되지 않습니다. 왜? 또한,'마음이 생각되면 "스왑"이라는 단어를 읽으십시오. "글쓰기"는 자극적입니다. -> 도서관 작가로서 당신은 일반적으로 일반적인 관행 (카피 + 스왑)을 알고 있고, 핵심은 '내 마음'입니다. 당신의 마음은 실제로 공용 인터페이스 뒤에 숨겨져 있습니다. 이것이 재사용 가능한 코드의 전부입니다. –
"... 거의 동일한 코드가 있습니다 ..."? 흠 .. 너는 틀린 일을해야만 해. 이를 위해 사용자 정의 함수를 사용할 필요성을 최소화하고 컴파일러가 모든 더러운 작업을 수행하도록하십시오. 이는 종종 자체 멤버 객체에 리소스를 캡슐화하는 것을 의미합니다. 몇 가지 코드를 보여줄 수 있습니다. 어쩌면 우리는 좋은 디자인 제안을 가지고 있을지도 모른다. – sellibitze
[연산자 = 및 복사 생성자 간의 코드 중복 줄이기] 가능한 복제본 (http://stackoverflow.com/questions/1477145/reducing-code-duplication-between-operator-and-the-copy-constructor) – mpromonet