2016-07-25 3 views
0

초보자 C++ 프로그래머가 있습니다. 내부 클래스 인 중첩 된 클래스가있는 Outer 클래스가 있다고 가정 해 보겠습니다. 내부에는 구성 중 포인터 멤버가 외부에 포함됩니다. 겉면에는 자신을 가리키는 새로운 Inner를 만들어 벡터에 추가하는 AddNewInner() 함수가 있습니다.포인터 멤버가 들어있는 중첩 클래스가있는 클래스의 인스턴스를 외부 클래스에 복사하는 방법은 무엇입니까?

class Outer { 

public: 

    class Inner { 
    public: 
     Inner(Outer* outerParent) : mOuterParent(outerParent) {} 
     Outer* mOuterParent; 
    } 

    void AddNewInner() { 
     Inner newInner(this); 
     mInnersVec.push_back(newInner); 
    } 

    vector<Inner> mInnersVec; 
} 

Outer의 새 인스턴스를 만들고 AddNewInner()를 호출하여 Inners를 벡터에 추가 할 때 잘 작동합니다. 그러나 Outer 인스턴스의 복사본을 만들려고 할 때 문제가 발생했습니다. Outer 복사본의 Vector는 복사본 자체를 가리 키지 않고 원래 Outer를 가리 킵니다.

Outer outerA; 
outerA.AddNewInner(); 
Outer* ptrA = outerA.mInnersVec[0].mOuterParent; // this points to outerA, good! 

Outer outerB = outerA; 
Outer* ptrB = outerB.mInnersVec[0].mOuterParent; // this still points to outerA, bad! 

필자는 원래 버전이 아니라 복사본을 가리키는 Inners의 벡터가 필요합니다. 이 작업을 수행하는 가장 좋은 방법은 무엇입니까? 아니면 동일한 작업을 수행 할 대체 방법이 있습니까?

+0

아 ....복사 생성자를 읽어야합니다. Google 사본 생성자, 딥 복사, 얕은 사본. 많은 참고 자료가 있습니다. – cplusplusrat

답변

0

정확합니다. 이것은 예상되는 동작입니다. C++에서 개체의 복사본을 만들 때 컴파일러는 복사 생성자을 사용합니다. 클래스에 대해 자신의 복사본 생성자를 작성하지 않은 경우 컴파일러에서 생성 한 복사본 생성자를 사용합니다.이 생성자는 차례대로 각 멤버에 대해 생성 된 복사 생성자를 차례대로 실행합니다. Outer를 복사 할 때

그래서, 이벤트의 순서는 다음과 같이 진행됩니다

  • 컴파일러는이 std::vector의 복사 생성자를 실행하는이 (생성) Outer
  • 에 대한 생성자를 복사 실행합니다. 이 생성자는 새 벡터에 대한 저장소를 할당 한 다음 각 요소에 대해 복사 생성자를 차례로 실행합니다.
  • Inner에 대한 (생성 된) 복사 생성자가 각 요소에 대해 실행되므로 멤버 포인터 (여전히 원본 Outer). Outer을 복사 할 때 Inner 요소를 업데이트하기 위해

, 당신은 당신이 원하는만큼 포인터를 업데이트 Outer에 대한 사용자 정의 복사 생성자를 작성해야합니다. 다음과 같은 것 :

Outer::Outer(const Outer& other) 
    : mInnersVec(other.mInnersVec) // Do initial vector copy 
{ 
    // Update vector elements 
    for (auto& elem : mInnersVec) { 
     elem.mOuterParent = this; 
    } 
} 

사용자 정의 복사본 생성자를 작성할 때마다 거의 항상 사용자 지정 할당 연산자도 작성해야합니다. 좋아하는 C++ 교과서에서 복사 및 할당에 대해 읽는 것이 좋습니다 :-).

0

클래스에 맞춤 copy constructor/assignment operator을 사용해야합니다. 이렇게하면 Outer* mOuterParent 변수의 전체 복사본을 만들 수 있습니다. 아마도 새로운 것을 만들 것입니다.

포인터를 복사 할 때 메모리의 특정 주소 공간을 가리키는 변수를 복사하고 있습니다. 포인터 만 복사하면 두 개의 '접근 자 변수'를 통해 동일한 '실제 변수'에 액세스 할 수 있습니다. 당신의 예에서

뜻이 항상 outer 클래스의 동일한 인스턴스에 포인트는 상관없이 특정 객체의 여러 사본이 당신이 만드는 방법이 포인터가 가리키는없는 특정 outer 객체의 Outer* mOuterParent 변수입니다.