2011-12-09 9 views
0

클래스에 참조 변수가있는 경우 오버로드 된 할당 연산자를 작성해야합니다. 이 문제를 해결하려면 어떻게할당 연산자 오버로드 다루기; 참조를 다시 할당 할 수 있습니까?

MyClass& MyClass::operator=(const MyClass& rhs) 
{ 
    if (&rhs != this) 
    { 
     myReference = rhs.myReference; 
    } 
    return *this; 
} 

: 당신은 같은 일을 할 수 없습니다, 따라서 인스턴스에 대한 참조를 한 번 설정하고 수 인상을

입니까?

EDIT - 좋아요. 그렇기 때문에 참조 연산자가있는 클래스에서 대입 연산자를 사용할 수 없다고 들었습니다. 그런데 왜 비주얼 스튜디오가 나에게 해줄까요? 프로그램이 실행되고 모든 것.

+2

사이드 노트 : 복사 스왑 관용구를 사용하면 '& rhs! = this' 체크가 중복됩니다 (http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap- 관용구). –

+0

@SirYakalot : 내 편집을 참조하십시오. 나는 이것이 당신을 위해 일들을 명확히하기를 바랍니다. –

답변

1

아니요, 참조 번호를 다시 입력 할 수 없습니다.

고려 :

int a = 42, b = 43; 
int &ar = a; 
ar = b; 

방법 컴파일러는 당신이 b을 참조 ar를 다시 장착하려고하는 것을 알고, 그리고 43a을 설정할 수 없습니다?

이 "문제"는 참조가 아닌 포인터를 사용하여 해결할 수 있습니다.

편집 :

확인이 그래서 내가 당신이 잘하는 참조 클래스에 할당 연산자를 사용할 수 없습니다 말했다 해요, 당신의 편집 당. 그런데 왜 비주얼 스튜디오가 나에게 해줄까요? 프로그램이 실행됩니다.

결론의 전제가 잘못되었습니다. 은 참조가 포함 된 클래스에서 대입 연산자를 사용합니다. 당신이 할 수없는 것은 참조를 다시 앉는 것입니다. 위의 코드에서 설명한 것처럼 ar = a;을 사용하여 참조를 다시 할당하려는 경우 ar을 다시 앉지 않고 ar이 참조하는 값을 변경합니다.

Visual Studio "어렵지 않게 할 수 있습니다". 오해는 Visual Studio에서 내리는 것입니다.그것은 당신이 참조를 다시 자리 잡도록 두지 않습니다. 그것은 당신이 참조의 가치를 바꾸게합니다. 이것이 의미하는 바를 분명히 해줄 수있는 예가 나와 있습니다.

#include <iostream> 
#include <string> 
using namespace std; 

class Foo 
{ 
public: 
    void dump() const 
    { 
     cout << "Foo instance " << showbase << this << "\n"; 
    } 
}; 

class Bar 
{ 
public: 
    Bar(Foo& foo) : foo_(foo) {} 
    Bar& operator=(const Bar& rhs) 
    { 
     foo_ = rhs.foo_; 
     return * this; 
    } 

    void dump() const 
    { 
     cout << showbase << "Bar instance " << this << "\t"; 
     foo_.dump(); 
    } 

private: 
    Foo& foo_; 
}; 

int main() 
{ 
    cout << "foo1: "; 
    Foo foo1; 
    foo1.dump(); 

    cout << "foo2: "; 
    Foo foo2; 
    foo2.dump(); 

    cout << "bar1 :"; 
    Bar bar1(foo1); 
    bar1.dump(); 

    cout << "bar2 :"; 
    Bar bar2(foo2); 
    bar2.dump(); 

    bar2 = bar1; 
    cout << "bar2 after assign :"; 
    bar2.dump(); 
} 

코드는 상기 2 Foo 개체 (foo1foo2)를 설정하고, 다른 Foo 참조를 각각 갖는 2 개 Bar 객체를 생성한다. Bar는 다음 실행하는, operator=이있다 : C++이 방법으로 당신이 다시 시트 참조를 허용하는 경우

foo_ = rhs.foo_; 

, foo_ 지금 Foo의 다른 인스턴스를 참조한다. 하지만 그렇지 않습니다. 이것은 foo_이 참조하는 것을 변경하지 않습니다. 대신 Foo에서 operator=을 호출합니다. 위의 코드를 실행하면 bar2에있는 Foo의 주소가 변경되지 않습니다. 참조를 다시 앉을 수 있다면 변경 될 것입니다.

+0

@Downvoter : downvote 이유는 무엇입니까? –

+0

그래서 참조가 포함 된 클래스에 대한 오버로드 된 대입 연산자를 작성할 수 있습니다. 이니셜 라이저 목록의 참조에 적합한 구문은 무엇입니까? – SirYakalot

+0

@SirYakalot : 간단하게'obj :: obj() : ref_ (ref) {}; ' –

0

당신은 참조를 사용하는 클래스와 할당 연산자를 만들지 만이 줄 수

myReference = rhs.myReference; 

참조를 다시 할당하지 않습니다. Reference가 참조하고있는 것을 재 할당합니다. 그래서, 그 할당 후에, myReference와 rhs.myReference는 이제 같은 객체를 참조하지 않습니다. 그러나 그들이 지금 참조하는 것들은 동등한 가치 (또는 그 유형에 대한 어떤 할당의 의미)를가집니다.

재 할당 가능한 참조가 필요하면 포인터를 사용하십시오. 그것이 바로 그들이 원하는 것입니다. 사실, 현대의 C++에서는 원시 포인터에 남은 유일한 용도입니다. 참조하는 객체가 동적으로 할당 된 경우 shared_ptr에 넣고 myReference를 shared_ptr 또는 weak_ptr 중 하나로 설정해야합니다.

+0

원시 포인터에 대해 이야기하기 시작했기 때문에 내 upvote를 제거했습니다. 그는 포인터를 사용해야하며, 스마트 포인터 여야합니다. –

+0

@BenVoigt : 가리키는 대상이 이미 스마트 포인터에 포함되어 있고 때로는 제어 할 수없는 경우에만 스마트 포인터를 사용할 수 있습니다. 스마트 포인터는 동적으로 할당 된 객체를위한 것이며 때때로 동적으로 할당되지 않은 객체에 대한 참조가 필요합니다. –

+0

사실, 그렇다고해서 아직 미가공 포인터가 여기에 적절하다는 의미는 아닙니다. –

0

두 단어로 - 할 수 없습니다. 참조는 실제 객체의 의미를 가지므로 대입 연산자는 실제로 참조 자체가 아닌 기본 객체에 대한 대입을 호출합니다.

+0

참조가있는 클래스에 대입 연산자를 작성하는 방법은 없습니다. – SirYakalot

+0

@SirYakalot : 아니요. 내 게시물을 참조하십시오. –

+0

@SirYakalot : 내게 보이지 않습니다. –

0

참조를 리바운드 할 수 없습니다. (글쎄, 배치 new 할 수 있지만 그걸하지 마십시오!)

하지만 당신이 생각하는대로하지 않더라도 코드는 합법적입니다. 레퍼 런트 (레퍼런스 대상)에 할당하는 것이 아니라 레퍼런스를 다시 바인딩하거나 재 할당하는 것이 아닙니다.

+0

하지만 괜찮습니까? 왜냐하면 우리는 단지 원래의 객체를 스스로 설정하고 있기 때문입니다. 또는 그 사본이 아직 자체 참조가 없다는 것을 의미합니까? – SirYakalot

+0

원하는 동작에 따라 다릅니다. 많은 경우, 지시 대상을 지정하는 것이 올바른 동작입니다. 두 객체는 ​​여전히 다른 메모리 위치를 참조하지만 메모리 위치의 값은 하나에서 다른 위치로 복사됩니다. –

0

코드는 그대로 작동하지만 이 아닌은 참조를 다시 지정합니다.

myReference = rhs.myReference; 

rhs.myReference에서 참조하는 개체를 myReference에 할당합니다. 따라서 할당이 이루어지기 전에 &myReference != &(rhs.myReference)이 참이라고 가정하면 할당 후에도 계속 true가됩니다. 그러나 해당 주소의 객체에는 동일한 값이 포함됩니다 (myReference == rhs.myReference 인 경우 operator==이 유형에 대해 정의되어 있고 비공식적 인 방식으로 작동합니다). 참조를 다시 지정하면 (불가능 함) 할당 된 &myReference == &(rhs.myReference)이 참일 것입니다. 따라서 실제 질문은 당신이 원하는 것입니다 : 에 의해 참조 된 객체를 this->myReference에 의해 참조 된 객체 (이 경우 코드는 괜찮습니다)에 복사하거나 this->myReference과 같은 객체를 참조로 복사 하시겠습니까? rhs.myReference (참조와 함께 사용할 수 없으므로 포인터를 사용해야합니다.)