c++ 객체를 인자로 넘기는 경우 질문 드립니다.

paaran00의 이미지

void CSendPacketChecker::addSendPacket(CSendPacket sendPacket)
{
	mSendPacketMap[sendPacket.getPacketId()] = sendPacket;	
	mSendPacketMap[sendPacket.getPacketId()].timerStart();
}

위와 같은 함수가 있다고 할때, 제가 알기로는 인자로 넘어오면서 복사생성자가 호출되고 sendPacket을
Map에 대입할 때도 복사생성자가 호출되어야 한다라고 생각이 드는데요.
로그를 찍어보면 대입할때는 일반 생성자가 호출이 되더라구요.
대입이라는것이 복사생성자를 호출하는게 아닌가요 ?

추가로 객체를 포인터로 넘기면 타이머가 돌아가고 일반 객체를 저렇게 넘겨서 사용하면 타이머가 안돌아가는 현상이 있는데요.

sendPacket.timerStart()는 객체가 함수가 끝나고 소멸되므로 안돌아가는걸 알겠는데, 이미 Map 컨테이너에 들어간 객체의 타이머를 시작시키는데 동작을 안하는 부분이 이해가 안되네요.

구글링을 해봐도 해당 케이스에 대한 부분을 설명할만한 자료를 찾기가 어려워 질문글을 남겨봅니다.
좋은 저녁되세요.

Anti-Lock의 이미지

일반 생성자와 복사 생성자 가 호출이 된다구요? 소멸자도 호출되겠죠?
그러면 그 코드를 보지 않은 상태에서는 왜 이상하게 동작하는지 막연히 추측할 수 밖에 없습니다.

paaran00의 이미지

제가 아직 개념이 확립되지않은것 같습니다.
답변감사드립니다.

 의 이미지

Quote:
위와 같은 함수가 있다고 할때, 제가 알기로는 인자로 넘어오면서 복사생성자가 호출되고

여기까지는 맞습니다.

Quote:
sendPacket을 Map에 대입할 때도 복사생성자가 호출되어야 한다라고 생각이 드는데요.

여기가 문제죠.

복사생성자가 호출되어야 할 거라고 막연히 생각하신 점으로부터 미루어 볼 때, 원래의 map mSendPacketMap에는 key가 sendPacket.getPacketId()인 item이 없었나 보죠?

문제를 잠시 일반화해보죠.
map<key_t, value_t> m에 어떤 key_t k로 접근하는 표현식 m[k]는 무엇을 반환할까요?

k를 key로 가지는 item이 m에 이미 있을 경우에는 문제가 간단합니다. 바로 그 item의 value를 반환하면 되죠.
특히 우리는 m[k] = v2와 같이 해당 item을 변화시킬 수 있기를 바라기 때문에, 이 표현식이 참조자를 반환하기를 바랄 것이고요.

문제는 k를 key로 가지는 item이 없을 경우입니다. 아시다시피 C++에서 포인터는 null pointer를 이용하여 값이 없음을 나타낼 수 있지만, 참조자에는 대응되는 개념이 없죠.

그래서 map의 설계자들은 이 문제를 해결하기 위해, 표현식 m[k]이 평가되는 동안, 즉 다시 말해 map m에 대해 operator[]이 호출될 때 key k를 가지는 item이 없으면, 그러한 item을 map에 삽입한 뒤 그 value를 반환하게 만들어 놨습니다.
그 과정에서 삽입되는 item의 value는 value_t에 대한 디폴트 생성자, 즉 아무 파라미터도 받지 않는 생성자를 통해 만들어지는 값을 가지게 되지요. 이게 바로 질문자님이 말씀하신 일반 생성자가 호출되는 이유입니다.
mapoperator[] 동작에 대해서는 레퍼런스 참조: http://en.cppreference.com/w/cpp/container/map/operator_at

그 다음엔 어떻게 되냐고요? 앞서 디폴트 생성자로 초기화된 value에 지정하신 sendPacket이 대입됩니다. 이 때 쓰이는 연산자는 복사 대입 연산자(copy assignment operator)가 되겠습니다. 이에 대해서도 레퍼런스 참조: http://en.cppreference.com/w/cpp/language/copy_assignment

Quote:
대입이라는것이 복사생성자를 호출하는게 아닌가요 ?

여기서부터는 비록 심증입니다만, 질문자님께서 일반 생성자와 복사 생성자에서는 로그를 찍었는데 복사 대입 연산자에서는 로그를 안 찍으신 점으로 볼 때, 복사 대입 연산자의 의미와 중요성에 대해서 잘 모르고 계시지 않은가 하는 의심이 드는군요.

만에 하나 그럴 경우를 대비해서 한 가지 더 말씀드려야겠네요. 복사 생성자를 직접 작성해야만 할 필요가 있었다면, 거의 대부분의 경우 복사 대입 연산자도 같이 작성해 주어야 합니다. 그렇지 않을 경우 컴파일러가 기본 구현을 해 주게 되는데, 두 함수 중 하나라도 기본 구현을 써서는 안 될 이유가 있었다면 다른 하나도 마찬가지일 가능성이 높다는 말씀입니다.

질문자님이 이 규칙을 어겼다면, 음, 아마도 timerStart()이 제대로 동작하지 않는 이유 중 하나가 이 문제일 가능성이 높습니다.

paaran00의 이미지

이정도까지 디테일하게 대답해주시는분이 계시다니 정말 감사하네요.
복사 대입 연산자라는 부분은 제가 알지못했던 부분이고 정확히 짚어주신것 같습니다.
공부에 도움을 주셔서 정말 감사드립니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.