2017-04-20 5 views
0

주 프로그램에서 선언 된 변수와 인스턴스화 된 클래스 객체 내부의 변수 사이의 메모리 주소 지정 차이점을 이해하려고 노력하고 있습니다!C++에서 "클래스 인스턴스화 된 객체 및 객체 주소 내부 변수"메모리 주소

내 질문은 "int a, int b"주 프로그램 내에서 예를 들어 두 개의 변수를 선언 할 때 메모리에서 특정 두 개의 주소가있는 4 + 4 바이트를 사용합니다. 예를 들어 "a는 메모리 0x248444에 있고 b는 0x248448에 있습니다."....이 경우에는 괜찮습니다. ...

"int c, int d"라는 두 변수가있는 클래스 인스턴스화 된 객체는 객체는 "0x248544"의 8 바이트 메모리 주소를 취하고 "int c 및 int d"의 주소는 어떻게됩니까?

int c 및 int d의 주소가 해당 개체 주소 "0x248544"안에 있습니까? int c 및 int d에 특정 주소가 있습니까?

어떻게 이해할 것인가/인스턴스화 된 클래스 개체 주소와 그 개체 안에있는 변수의 주소의 차이점은 무엇입니까?

내 질문에 분명 ....

인터넷에서 검색 후, 나는 "는 C++ 객체 모델 내부"하지만 인스턴스화 된 클래스 객체에 선언 된 변수에 대한 메모리 차이의 기본적인 이해라는 책을 발견 희망 main에 선언 된 변수. 누군가 나 자신을 분명히하도록 도와주세요.

미리 감사드립니다.

+0

메모리 레이아웃은 플랫폼에 따라 다릅니다. 예를 들어, 멤버 간의 패딩은 특정 플랫폼의 멤버 유형에 대한 크기 및 정렬 요구 사항에 따라 달라집니다. 최신 표준에 대해서는 잘 모르겠지만, 잠시 동안 동일한 액세스 지정자를 가진 멤버에 대해서만 멤버 순서가 유지된다는 것을 알고 있습니다. –

+0

related/dupe : http://stackoverflow.com/questions/26939609/how-is-the-memory-layout-of-a-class-vs-a-struct – NathanOliver

+0

클래스 객체는 POD 인 경우 구조체와 레이아웃이 같습니다. (패딩 포함). 변수의 주소가 클래스 자체에서 오프셋 될 가능성이 있습니다. 'offsetof (cls, some_var)'를 사용할 수 있습니다. – Brandon

답변

2

좋아,이 같은 클래스 C가 :

class C 
{ 
    int c; 
    int d; 
}; 

클래스 C (C c)의 인스턴스가 일부 메모리를 차지 것, 그것은 필요 (제공 INT는 4 바이트 큰 -입니다 반드시 경우 모든 기계에, 그러나) 8 바이트.

인스턴스가 주소 0x248544에있는 경우이 주소의 바이트 + 다음 후속 바이트를 정확하게 차지합니다. 위의 조건과 같은 간단한 클래스에서 c는 다음 8 바이트 중 처음 4 바이트를 차지합니다.

그래서 c.c은 정확히 c과 동일한 주소이고 c.d은 4 바이트 뒤에 위치하고 있으므로 주소는 0x248548입니다.

첫 번째 구성원이 반드시 개체와 주소가 같지는 않습니다. 우리의 클래스 C 수정할 수 있습니다 : (!)

class C 
{ 
    virtual ~C() { } // virtual destructor -> C gets virtual! 
    int c; 
    int d; 
}; 

이제는 sizeof (C)이 될 것입니다 (16) (제공 포인터 현대 64 비트 하드웨어로, 8 바이트의 스토리지를 필요). 왜? 이 클래스는 보통 C 클래스의 첫 번째 (보이지 않는) 멤버 인 vtable에 대한 추가 포인터를 가져옵니다.

따라서는 여전히 주소 0x248544에 있지만 vtable에 대한 (보이지 않는) 포인터는이 주소를 공유합니다. c.c이 이후에 나오므로 주소 0x2484c에 있고 c.d은 0x24850에 있습니다. 이와 관련

, C++하지만,이 개 이후의 구성원이 필요하지 않습니다, ++

모두 C와 C에서 ... 구조체의 첫 번째 멤버는 항상 구조체 자체의 주소를 공유 C, 다른 서로 "만져야"할 때, 그 사이에 몇 바이트의 패딩이있을 수 있습니다 - 키워드 바이트 정렬.

또한, C++ 클래스의 멤버를 재정렬 할 수 : C에서 반면 구조체 부재 ab 전에 선언 된 경우, 다음 a 메모리에 b 앞에 배치해야도에만 필요 ++ C 인 같은 접근성을 가진 회원들에게!

class C 
{ 
    int a; 
public: 
    int b; 
private: 
    int c; 
}; 

현재 허용되는 컴파일러

은 그대로 순서를두고 있지만, 그것은뿐만 아니라 앞 또는 다른 두 후 b을 배치 할 수 있습니다 - 단지 ac 다음에 위치 할 수 없습니다.

긴 이야기 짧은 결론 :이 모든 메모리 레이아웃 물건이 훨씬 더 당신은 아마 그것이 될 예상보다 복잡하다 ... vtable을에

사이드 참고 : vtable에 포인터는 점에서 (거기에있을 필요가 없습니다 C++ 표준으로) - 어떤 컴파일러 벤더가 다형성을 구현하기위한 더 나은 솔루션을 찾으면 그들은 인 경우 찾을 수 있습니다. 그러나 vtable은 사실상의 표준이며 일종의 표준입니다.

+0

멋지게 설명했습니다! 정확히 내가 기대하고있는 것! 감사합니다. – Macs

1

클래스 인스턴스를 멤버 변수의 엔벌 로프로 간주 할 수 있습니다. 클래스 인스턴스의 크기는 멤버 변수의 크기와 이들 사이의 선택적인 패딩의 합입니다. 종종 (상속과 다형성이 혼란 스러울 수 있음) 첫 번째 멤버 변수의 주소는 클래스 인스턴스의 주소와 동일합니다. 멤버의 주소를 가져 와서 디버거에서 조사하여 작동 방식을 확인할 수 있습니다. 예 : c에 의해 점령

class C 
{ 
public: 
    int a = 1; 
    int b = 2; 
}; 

C c; 
int* p_a = &c.a; 
int* p_b = &c.b; 

확인 메모리, 당신은 값 내부 12를 볼 수 있습니다.

멤버 변수의 순서는 유지되며 패딩 때문에 클래스 인스턴스의 크기에 영향을 줄 수 있습니다.

빈 클래스의 인스턴스

이 주소를 가지고 있어야하고 그래서 그 크기가 결코 0

회원 기능이없는 것은 다른 이야기입니다. 또한 메모리에있는 동안 모든 인스턴스에서 공유되므로 인스턴스와 별도로 단일 위치에 저장됩니다.

+0

신속한 답장을 보내 주셔서 감사합니다. – Macs