2011-08-24 2 views
6

배경 : 많은 변수가있는 복잡한 클래스가 있습니다.operator =?에서 placement new (this)를 사용할 수 있습니까?

초기화 도구 목록에서 호출 된 멤버 변수 복사본 생성자 중 일부가 할당을 수행합니다.

질문 : operator=을 만들어야합니다. 오히려 나는 단순히 다음을 수행 할 수 있습니다, 등 등 등 대체되고있어 할당 대신 초기화 목록 및 해제 메모리와 기존의 constructor에 복제 및보다 : 즉

Applepie& Applepie::operator=(const Applepie &copy) 
{ 
    if(this != &copy) 
    { 
     this->~Applepie(); // release own object 
     new(this) Applepie(copy); // placement new copy constructor 
    } 
    return *this; 
} 

, 배치 다음에 자기를 파괴하는 것입니다 연산자와 의미 적으로 동일한 새로운 복사 생성자 =?

이것은 반복 코드를 크게 줄이고 각 변수를 올바르게 초기화했음을 확인하는 것으로 할당 중에 약간의 효율성 손실이 발생할 수 있음을 나타냅니다. 나는 더 무언가를 놓치고 있니?

이론적 설명 : 실제 수업에는 약 30 개의 약점이 있습니다. 나는 복사 생성자와 대입 연산자가 모두 30 개를 복사해야한다는 것과 코드가 갈라져 두 작업이 다르게 작업하게된다는 사실에 우려하고있다.

+4

복사본 ctor가 throw되면 개체가 끊어져서 안전을 보장 할 수 없습니다. –

+1

@R Martinho - 그것은 내가 수동으로 각 변수를 할당했다면 복사 연산자가 던져 버릴 수있는 모든 상황이 던져 버릴 것이라고 생각합니다. 그래서 ... 여전히 동일하게 보입니까? – jcwenger

+3

문제는'operator ='throwing이 아니며'operator ='객체가 유효하지 않은 상태로 남습니다! 파괴되었습니다. –

답변

6

"예외적 인 C++"상태의 허브 셔터가 예외적 인 것은 아닙니다. 즉, new 동안 또는 새 객체의 생성 중에 잘못된 것이 있으면 할당의 왼쪽 피연산자가 잘못 (정의되지 않음) 상태가되어 더 많은 문제가 있음을 의미합니다. copy & swap idiom을 사용하는 것이 좋습니다.

Applepie& Applepie::operator=(Applepie copy) 
{ 
    swap(m_crust, copy.m_crust); 
    swap(m_filling, copy.m_filling); 
    return *this; 
} 

개체가 Pimpl 관용구 (구현 포인터)를 사용

또한, 스왑은 두 포인터를 변경하여 수행됩니다.

+1

+1 'swap'은 훌륭한 저평가입니다. 함수 ... 추가 장점 : 인수가 rvalue 인 경우 컴파일러는 복사 elision을 수행 할 수 있습니다. –

+0

그래서 ... 내 문제는 내 실제 클래스에 약 30 가지 변수가 있다는 것입니다. 내 복사 생성자는 초기화리스트에 30 개의 변수를 모두 가지고있다. 복사 및 스왑에는 여전히 30 번의 스왑() 호출이 필요합니다. 제 목표는 Applepie 파이 (원본)의 가능성을 줄이는 것입니다. 및 Applepie 사과; 사과 = 원래; 결과가 다릅니다. – jcwenger

+0

@ jcwenger : 네, 문제가 있습니다. 따라서 * Pimpl * 관용구의 후보가 될 수도 있지만 전환하기 전에 비용이 많이 드는 것으로 간주하십시오. 각 구성원 액세스는 포인터를 통해 진행됩니다. 또 다른 아이디어는'Applepie' 클래스를 더 작은 조각으로 나누는 것입니다. 한 클래스에 30 명의 데이터 멤버가있는 경우 디자인에 문제가있을 수 있습니다. –

0

Rene의 대답 외에도 ApplePie가 실제 객체의 기본 클래스 인 경우 ApplePie가 객체를 잘못된 유형의 객체로 대체하는 경우 발생할 수있는 문제가 있습니다.

+1

개체가 Handle-Worker 관용구에 구현되어 있지 않으면 operator =는 * object slicing *을 수행합니다. –

관련 문제