2011-10-26 3 views
25

참조 멤버가있는 대입 연산자를 만드는 올바른 방법입니까?참조 멤버가있는 할당 연산자

#include <new> 

struct A 
{ 
    int &ref; 
    A(int &Ref) : ref(Ref) { } 
    A(const A &second) : ref(second.ref) { } 
    A &operator =(const A &second) 
    { 
     if(this == &second) 
      return *this; 
     this->~A(); 
     new(this) A(second); 
     return *this; 
    } 
} 

컴파일하고 잘 실행 보이지만, C++ 경향 적어도 예상 정의되지 않은 동작을 표면, 그것의 불가능을 말하는 모든 사람들은, 내가 놓친 몇 가지 잡았다가 있다고 생각합니다. 내가 놓친 게 있니?

+0

, 연산자'에 대한 인수 ='와 복사 생성자는 const를 참조해야한다. –

+1

'this'는 메모리 블록의 시작 부분에 대한 포인터 일 필요가 없기 때문에 정확성은 표준 레이아웃 유형으로 제한 될 수 있습니다. –

+6

이 작업을 수행해야하는 경우 참조를 사용하여 다시 생각해 보시기 바랍니다. – bames53

답변

31

구문 상 올바릅니다. 그러나 새 게재 위치가 throw되면 은 파괴 할 수없는 개체로 끝납니다. 다른 누군가가 수업에서 파생 된 경우 재앙 인 은 말할 것도 없습니다. 그냥하지 마.

해결책은 간단합니다. 클래스가 할당을 지원해야하는 경우 은 참조 멤버를 사용하지 마십시오. 나는 클래스를 참조 인수를 취하는 많은 수업을 가지고 있지만 클래스가 과제를 지원할 수 있도록 포인터로 저장합니다. 또 다른 해결책은 (기능 헤더)를 reference_wrapper 클래스를 사용하는 것입니다

struct A 
{ 
    int* myRef; 
    A(int& ref) : myRef(&ref) {} 
    // ... 
}; 
+0

+1, 그건 내가하는 일이다. –

+0

나는 이것을 좋아한다 - 똑 바른 해결책! – aardvarkk

3

내가 아는 한 기술적으로 정확하지만 문제가 발생합니다. 예를 들어, A의 파생 클래스에서 대입 연산자가 새 객체를 생성 (분할)하므로 어떤 일이 발생하는지 고려하십시오. 레퍼런스를 클래스 내의 포인터로 바꿀 수 없습니까?

게다가 복사 생성자와 할당 연산자는 보통 const&에 의해 인수를 취합니다.

+0

어떻게 이런 문제가 발생합니까? –

1

당신이하는 일은 정확하지만 복사 할당 연산자를 작성하는 것은 예외가 아닙니다. 또한 참조 멤버가 아닌 포인터 멤버를 사용하는 것을 고려해야합니다.

Copy and Swap Idiom을 사용하여 구현해야합니다. 구현보다 3 가지 장점이 있습니다.

+0

그렇다면 참조를 바꾸는 방법은 무엇입니까? –

+0

@ChristianRau : 당신은 당신 자신의'swap' 함수를 구현할 것입니다. –

+0

예, 아마도 참조를 바꿔야 할 것입니다. –

2

: 같은 방법으로

struct A 
{ 
    A(int& a) : a_(a) {} 
    A(const A& a) : a_(a.a_) {} 

    A& operator=(const A& a) 
    { 
     a_ = a.a_; 
     return *this; 
    } 

    void inc() const 
    { 
     ++a_; 
    } 

    std::reference_wrapper<int>a_; 

};