클래스에서 구조체를 멤버 변수로 갖는 경우

parkon의 이미지

안녕하세요,

갑자기 뭔가 홀린 것처럼 헷갈리네요.
구조체를 클래스의 멤버 변수로 갖는 경우, 그 구조체가 변형이 될때마다
그 구조체를 소멸시킨 후, 새로운 구조체를 생성시키는 건가요 ?
즉 제 코드가

class MyClass {
// ...
private:
   TList fList;
};

이런식으로 되어 있고, 여기서 TList는 Cern에서 개발된 ROOT라는 프로그램에서 정의된 class인데
대충 std::list하고 비슷한 녀석입니다.
위처럼 했더니 이 클래스의 (저 fList에 연관되어 있는) 멤버 함수를 부를때마다 fList의 주소가
바뀌는 군요.

구조체를 멤버변수로 갖고 싶으면,
거의 무조건 아래처럼 포인터를 이용해서 클래스를 정의해야 하는 걸까요 ?

class MyClass2 {
// ...
private:
   TList* fListPtr;
};
 의 이미지

fList의 주소는 그것을 포함하고 있는 MyClass 객체 인스턴스의 주소에 의해 완전히 결정됩니다.
즉 똑같은 인스턴스에 대해 fList 멤버의 주소를 취한다면 달라질 이유가 전혀 없습니다.

제공된 코드만으론 도저히 무슨 일을 겪고 계신 건지 알 수가 없군요. MWE 부탁드립니다.
(MWE에 대해서는 https://kldp.org/node/155341, https://kldp.org/node/155515 참조)

parkon의 이미지

아, 덕분에 제가 어디에서 헤매고 있는지 알것 같습니다.
저 fList가 아닌 MyClass객체의 주소가 바뀌고 있었던 것 같습니다,
까딱 했으면 멀쩡한 코드들 다 엎을뻔 했네요 ..., 감사합니다 !

다시 조금 다른 질문을 드리자면,
저 fList가 모든 MyClass 객체에 항상 필요한 경우라면,
저 위에 제가 쓴 첫번째 방법이
두번째 포인터를 쓴 MyClass2에 비해 나쁘지 않다는 말씀이시지요 ?

 의 이미지

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를 떠올리시겠죠. 그래도 여전히 복사는 따로 해 줘야 하겠습니다만.

기타 등등. 뭐 하나하나 보시면 아시겠지만 별 거 없습니다. 그렇다곤 해도 포인터를 써서 얻을 수 있는 점이 뚜렷하지 않다면 일부러 짊어질 필요까지는 없는 짐들이지요. 취미삼아 그렇게 하시겠다면야 말릴 이유는 없지만요.

parkon의 이미지

자세한 설명에 감사드립니다 !!
솔직히 제가 초보라 말씀하신 unique_ptr은 처음 듣지만
대충 말씀하시는 바는 알것 같습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.