2013-03-19 2 views
2

나는 질문했습니다 this. 제 질문은 지금 입니다 어떻게이 작동합니까? 좀 더 자세히 설명하기 위해 아직 초기화되지 않은 객체를 어떻게 가리킬 수 있습니까? 나는이 MWE를 만들었고 그 객체가 할당 된 사본이 아니라 복사 된 것임을 보여줍니다. 객체는 아직 초기화되지 않았습니다. 그러나 객체를 가리킬 수 있습니다.아직 초기화되지 않은 회원을 가리키고 있습니다

#include <iostream> 

class Foo { 
public: 
    int x; 

    Foo(const Foo& ori_foo) { 
     std::cout << "constructor" << std::endl; 
     x = ori_foo.x; 
    } 

    Foo& operator = (const Foo& ori_foo) { 
     std::cout << "operator =" << std::endl; 
     x = ori_foo.x; 
     return *this; 
    } 

    Foo(int new_x) { 
     x = new_x; 
    } 
}; 

class BarParent { 
public: 
    Foo *p_foo; 

    BarParent(Foo* new_p_foo) : p_foo(new_p_foo) 
    { 
     std::cout << (*new_p_foo).x << std::endl; 
    } 
}; 

class BarChild : public BarParent { 
public: 
    Foo foo; 

    BarChild(Foo new_foo) 
     :BarParent(&foo) //pointer to member not yet initialised 
     ,foo(new_foo) // order of initilization POINT OF INTEREST 
     {} 
}; 

int main() { 
    Foo foo(101); 

    BarChild bar(foo); 

    std::cout << bar.p_foo->x << std::endl; 
std::cout << bar.foo.x << std::endl; 
} 

출력 :

constructor 
0 
constructor 
101 
101 

메모리 처리하는 방법의 세부 사항에 점점 두려워하지 마십시오. 그리고, 모든 회원이 거주하는 곳. 이 라인

BarChild bar(foo); 

BarChild 개체에 대한 컴파일러 보유 충분한 스택 공간에서

+0

아직 명확하지 않은 경우 알려주십시오 – aiao

+0

죄송합니다. 실수로 편집되었습니다. : BarParent (& foo) – aiao

+1

BarParent 생성자에서 Foo 값을 인쇄 해 보았습니까? – nonsensickle

답변

5

할당 초기화에 착각하지 마십시오. 생성자가 호출되기 전에 BarChild :: foo가 할당되기 때문에 BarParent :: p_foo가 가리키는 위치가 잘 정의됩니다. Foo의 생성자는 BarChild :: foo를 초기화합니다. 그러나 생성자가 호출되기 전에 BarChild :: foo에서 읽지 않으려면 순서를 알 수 없습니다.

+0

구성원의 초기화가 다른 구성원에 종속적이지 않으면; 이 코드는 불쾌한 놀라움없이 완벽하게 사용할 수 있습니다. 그게 맞습니까? – aiao

+0

@aiao 멤버 초기화가 끝날 때까지 멤버를 읽지 않으면 안전합니다.이것은 당신이 말하는 것과 약간 다르지만,이 예에서는 다소 차이가 있습니다. – tletnes

+0

다른 멤버의 초기화 이외의 다른 멤버를 사용할 수있는 사람에 대해 좀 더 자세히 설명해 주시겠습니까? – aiao

3

는 다음 개체의 수명을 시작하는 생성자를 호출합니다. 객체 내에서 foo 구성원은 고정 된 오프셋을 가지고 있습니다. 모든 BarChild 객체는 foo 구성원이 동일한 오프셋 내에 있습니다. 따라서 this 포인터는 생성자 내에 알려진 주소 (스택에 bar의 주소 임)가 있으므로 this->foo은 심지어 해당 주소의 메모리가 아직 초기화되지 않은 경우에도 알려진 주소에서. BarChild 오브젝트는 각 멤버가 초기화되고 크기가 고정되며 모든 멤버의 공간이 이미 초기화되기 전에 "예약 됨"상태이므로 "커지면"커지지 않습니다. 아직

char raw_memory[sizeof(Foo)]; // define block of uninitialized memory 
char* addr = raw_memory;  // take address of uninitialized memory 
new (raw_memory) Foo;   // initialize memory 

개체가 존재하지 않으며, 그것을 사용하는 유효 아니지만, 그 주소가 초기화되고 사전에 알려져

이것은 다소 유사하다.