클래스에서 구조체를 멤버 변수로 갖는 경우
글쓴이: parkon / 작성시간: 금, 2016/11/18 - 9:03오후
안녕하세요,
갑자기 뭔가 홀린 것처럼 헷갈리네요.
구조체를 클래스의 멤버 변수로 갖는 경우, 그 구조체가 변형이 될때마다
그 구조체를 소멸시킨 후, 새로운 구조체를 생성시키는 건가요 ?
즉 제 코드가
class MyClass { // ... private: TList fList; };
이런식으로 되어 있고, 여기서 TList는 Cern에서 개발된 ROOT라는 프로그램에서 정의된 class인데
대충 std::list하고 비슷한 녀석입니다.
위처럼 했더니 이 클래스의 (저 fList에 연관되어 있는) 멤버 함수를 부를때마다 fList의 주소가
바뀌는 군요.
구조체를 멤버변수로 갖고 싶으면,
거의 무조건 아래처럼 포인터를 이용해서 클래스를 정의해야 하는 걸까요 ?
class MyClass2 { // ... private: TList* fListPtr; };
Forums:
fList의 주소는 그것을 포함하고 있는
fList의 주소는 그것을 포함하고 있는 MyClass 객체 인스턴스의 주소에 의해 완전히 결정됩니다.
즉 똑같은 인스턴스에 대해 fList 멤버의 주소를 취한다면 달라질 이유가 전혀 없습니다.
제공된 코드만으론 도저히 무슨 일을 겪고 계신 건지 알 수가 없군요. MWE 부탁드립니다.
(MWE에 대해서는 https://kldp.org/node/155341, https://kldp.org/node/155515 참조)
아, 덕분에 제가 어디에서 헤매고 있는지 알것
아, 덕분에 제가 어디에서 헤매고 있는지 알것 같습니다.
저 fList가 아닌 MyClass객체의 주소가 바뀌고 있었던 것 같습니다,
까딱 했으면 멀쩡한 코드들 다 엎을뻔 했네요 ..., 감사합니다 !
다시 조금 다른 질문을 드리자면,
저 fList가 모든 MyClass 객체에 항상 필요한 경우라면,
저 위에 제가 쓴 첫번째 방법이
두번째 포인터를 쓴 MyClass2에 비해 나쁘지 않다는 말씀이시지요 ?
fList가 자신이 포함된 MyClass 객체
fList가 자신이 포함된 MyClass 객체 인스턴스와 생사고락을 함께한다면, 즉 다시 말해
1) MyClass 인스턴스가 생성될 때 같이 생성되고
2) 소멸될 때 같이 소멸하고
3) 복사될 때 같이 복사되고(복사 생성과 복사 배정 모두)
4) 이동될 때 같이 이동한다면(C++11 이상, 이동 생성과 이동 배정 모두)
단언컨대 MyClass가 MyClass2보다 낫습니다.
물론 MyClass2로도 MyClass가 할 수 있는 모든 걸 할 수 있죠. 하지만...
1) MyClass2 인스턴스 하나 당 포인터 한 개(아키텍처에 따라 다르지만 x86-64에서 8바이트) 이상의 메모리가 더 필요합니다. 뭐 사실 요즘 세상에 별 거 아닙니다.
2) MyClass2 인스턴스 하나 당 TList 인스턴스 하나가 힙에 따로 할당되므로 힙의 단편화가 아주 약간 가속됩니다. 이것도 사실 요즘 세상엔 별 거 아닙니다.
3) TList 인스턴스는 힙에 생성되므로 자신이 속한 MyClass2의 다른 멤버들과는 상당히 떨어져 있게 됩니다. 이는 Locality를 감소시켜 CPU 캐시가 비효율적으로 쓰이게 만듭니다. 이 효과는 MyClass 객체가 작을수록 두드러집니다. 사실 MyClass를 엄청 많이 만들고 자주 쓰지 않는 한 그렇게까지 신경쓰일 정도는 아닙니다.
4) MyClass2 인스턴스를 위한 메모리가 할당되었는데 TList를 위한 메모리가 할당 실패되는, 요즘 PC 환경에서는 길 가다가 벼락맞는 것과 비슷한 느낌의 사태가 벌어질 여지가 생깁니다. 뭐, 어차피 대응되는 상황에서 MyClass였다면 통째로 생성에 실패했을 테니 무척 꼼꼼하고 편집증적인 프로그래머가 아니라면 따로 신경써 줄 필요는 없겠지요. 되려 이렇게 세밀하게 컨트롤해줄 수 있다는 점을 좋아하시는 분이 계실지도.
5) 포인터 멤버를 가짐으로써 MyClass2는 더이상 디폴트 복사/이동 생성자/배정 연산자를 이용할 수 없게 됩니다. 그랬다간 얕은 복사가 이루어질 테니까요. C++에 제법 능숙하여 객체의 깊은 복사를 예외 안전성을 갖추어 작성하는 일 따위는 취미 활동쯤으로 여기고 계신다면 사실 별 문제가 안 됩니다. 설령 그 정도까지는 아니더라도 C++11을 잘 아신다면 바로
unique_ptr
를 떠올리시겠죠. 그래도 여전히 복사는 따로 해 줘야 하겠습니다만.기타 등등. 뭐 하나하나 보시면 아시겠지만 별 거 없습니다. 그렇다곤 해도 포인터를 써서 얻을 수 있는 점이 뚜렷하지 않다면 일부러 짊어질 필요까지는 없는 짐들이지요. 취미삼아 그렇게 하시겠다면야 말릴 이유는 없지만요.
자세한 설명에 감사드립니다 !!
자세한 설명에 감사드립니다 !!
솔직히 제가 초보라 말씀하신 unique_ptr은 처음 듣지만
대충 말씀하시는 바는 알것 같습니다.
댓글 달기