<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
	<channel>
		<title>김윤수의 이상계를 꿈꾸며</title>
		<link>http://yesarang.tistory.com/</link>
		<description>이상계는 이쪽에 속해있지 않고 저쪽에 속해 있다. 이쪽에 사는 우리는 이쪽에 머무르지 않고 저쪽을 꿈꾸며 살아야 한다. 여기 오는 모든이들이 저쪽의 충만함을 이쪽에서의 매일의 삶에 경험할 수 있기를...
E-mail: (yesarang) at (yahoo.co.kr)</description>
		<language>ko</language>
		<pubDate>Thu, 29 Oct 2009 15:19:14 +0900</pubDate>
		<generator>Tistory 1.1 (http://www.tistory.com/)</generator>
		<image>
		<title>김윤수의 이상계를 꿈꾸며</title>
		<url><![CDATA[http://cfs2.tistory.com/upload_control/download.blog?fhandle=YmxvZzMyMTg1QGZzMi50aXN0b3J5LmNvbTovYXR0YWNoLzAvMzkuanBn]]></url>
		<link>http://yesarang.tistory.com/</link>
		<description>이상계는 이쪽에 속해있지 않고 저쪽에 속해 있다. 이쪽에 사는 우리는 이쪽에 머무르지 않고 저쪽을 꿈꾸며 살아야 한다. 여기 오는 모든이들이 저쪽의 충만함을 이쪽에서의 매일의 삶에 경험할 수 있기를...
E-mail: (yesarang) at (yahoo.co.kr)</description>
		</image>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/yoonsookim" type="application/rss+xml" /><feedburner:emailServiceId>yoonsookim</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
			<title>C++ 이야기 서른한번째: 왜 예외를 쓰는 게 좋을까요?</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/agJ7vyZqtRY/368</link>
			<description>&lt;p&gt;&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;If you're an English speaker, please follow &lt;a style="color: rgb(0, 0, 0);" title="[http://opensw.wikidot.com/cpp-fundamentals-exception]로 이동합니다." target="_blank" href="http://opensw.wikidot.com/cpp-fundamentals-exception"&gt;this link&lt;/a&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;이글의 최신본은 항상 &lt;/span&gt;&lt;a style="color: rgb(25, 61, 169); font-weight: bold;" title="[http://opensw.wikidot.com/cpp-fundamentals-exception-ko]로 이동합니다." target="_blank" href="http://opensw.wikidot.com/cpp-fundamentals-exception-ko"&gt;&lt;/a&gt;&lt;a style="font-weight: bold; color: rgb(0, 0, 0);" title="[http://opensw.wikidot.com/cpp-fundamentals-exception-ko]로 이동합니다." target="_blank" href="http://opensw.wikidot.com/cpp-fundamentals-exception-ko"&gt;여기&lt;/a&gt;&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;에 있습니다. 최신본은 코드에 syntax highlighting도 되어 있고, 철자법도 맞추고 부가정보도 계속 업데이트 하고 있습니다.&lt;/span&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;여러분은 서브루틴에 에러가 발생했다는 걸 알려주려 할 때 C++ 예외를 사용하시나요? 쓰시지 않는다면, 왠가요? 에러를
나타내는 특별한 에러 코드를 되돌려주면 되기 때문에 전혀 사용할 필요가 없다라고 답변하실지도 모르겠습니다. 사용하신다면,
왠가요? 이 질문에 대해서는 다른 방법이 있나요?라고 오히려 반문하시는 분이 있을지도 모르겠네요.&lt;/p&gt;
&lt;p&gt;C++에 예외가 도입된 이유를 밝하기 위해 이 글을 작성하게 됐습니다. 이 설명을 통해 위에 두 부류의 분들 모두 예외에 대해 더 잘 이해하게 되고, 예외를 이용하여 더 좋은 코드를 작성하는데 도움이 되시리라 생각합니다.&lt;/p&gt;
&lt;p&gt;C++에 왜 예외에 도입되었다고 생각하세요? 왜 아직도 Java나 C#같은 언어가 C++의 예외를 물려 받았다고
생각하세요? 그런데는 틀림없이 어떤 이유가 있을 것입니다. 그 이유는 바로 결함내성(fault-tolerant) 소프트웨어를
쉽게 작성하도록 하기 위한 것입니다.&lt;/p&gt;
&lt;p&gt;C/C++ 같이 상태를 갖는 프로그래밍 언어에서 에러 처리를 한 후에도 일관성있는 상태를 유지해야 한다는 건 결함내성을 달성하는데 있어 정말 까다로운 문제입니다.&lt;/p&gt;
&lt;p&gt;예를 들어, 다음과 같이 어떤 파일을 열고 데이터를 읽어들이는 짤막한 C 코드를 생각해 보기로 하겠습니다.

&lt;/p&gt;
&lt;pre&gt;char*
OpenAndRead(char* fn, char* mode)
{
  FILE* fp = fopen(fn, mode);
  char *buf = malloc(BUF_SZ);
  fgets(buf, BUF_SZ, fp);
  return buf;
}
&lt;/pre&gt;
&lt;p&gt;OpenAndRead()의 목적이 워낙 간단하고 분명하니, 그 구현도 무척이나 간단하고 읽기도 쉽고 이해하기도 쉽습니다.
위 코드는 모든 서브루틴이 잘 수행된다면 잘 작동할 것입니다. 그렇지만 'fn' 파일이 없거나 파일에 대한 접근 권한이 없다면
어떻게 될까요? malloc() 이나 fgets() 이 실패하면 어떻게 될까요? 위 코드를 결함내성이 있게 만들려면 각 서브루틴
호출 후에 에러가 발생했는지 확인해보고, 에러가 발생했다면 어떤 행동을 취해야할 것인지 결정해야 합니다. 그 취해야할 행동이
여기서는 단순히 에러 메시지를 출력하고 획득했던 자원들을 해제하고, -1 을 리턴하는 걸로 가정해 보겠습니다. 그렇다면 코드를
다음과 같이 수정할 수 있겠지요.&lt;/p&gt;
&lt;pre&gt;int
OpenAndRead(char* fn, char* mode, char** data)
{
  *data = NULL;
  char* buf = NULL;
  FILE* fp = fopen(fn, mode);
  if (!fp) {
    printf("Can't open %s\n", fn);
    return -1;
  }
 
  buf = malloc(BUF_SZ);
  if (!buf) {
    printf("Can't allocate memory for data\n");
    fclose(fp);
    return -1;
  }
 
  if (!fgets(buf, BUF_SZ, fp)) {
    printf("Can't read data from %s\n", fn);
    free(buf);
    fclose(fp);
    return -1;
  }
 
  *data = buf;
 
  return 0;
}
&lt;/pre&gt;
&lt;p&gt;두 개의 코드를 비교해 보니 느낌이 어떠세요? 두번째 버전은 주 알고리즘을 처리하는 부분과 에러를 처리하는 부분이 막 섞여 있어서 읽기도 힘들고 이해도 힘들어졌습니다. 게다가 라인수도 많아져서 일을 더 많이해야하네요.&lt;/p&gt;
&lt;p&gt;예외를 사용하면 이런 문제가 발생하지 않습니다. 한 번 fopen(), malloc(), fgets() 이
FileDoesNotExist, FileNotAccessible, MemoryExhausted, EndOfFile 라는 예외를
발생시킨다고 가정해 보겠습니다. 그렇다면 다음과 같이 코드를 변화시킬 수 있을 것입니다.&lt;/p&gt;
&lt;pre&gt;int
OpenAndRead(char* fn, char* mode, char** data)
{
  *data = NULL;
  char* buf = NULL;
  FILE* fp = NULL;
  try {
    fp = fopen(fn, mode);
    buf = malloc(BUF_SZ);
    fgets(buf, BUF_SZ, fp);
    *data = buf;
    return 0;
  }
  catch (const FileDoesNotExist&amp;amp;) {
    printf("Can't open %s\n", fn);
  }
  catch (const FileNotAccessible&amp;amp;) {
    printf("The access %s is not permissible for %s\n", mode, fn);
  }
  catch (const MemoryExhausted&amp;amp;) {
    printf("Can't allocate memory for data\n");
    fclose(fp);
  }
  catch (const EndOfFile&amp;amp;) {
    printf("Can't read data from %s\n", fn);
    fclose(fp);
    free(buf);
  }
 
  return -1;
}
&lt;/pre&gt;
&lt;p&gt;OpenAndRead() 주 제어 흐름이 이제 에러 처리와 깔끔하게 분리가 된 걸 보실 수 있겠죠?
OpenAndRead() 이 버전은 좀 더 읽기 쉽게 됐네요. 그렇지만 아직도 라인수가 좀 많은 편입니다. 실상 예외가 발생했을
때 이루어지는 "스택 풀기(stack unwinding)"이라는 과정을 이해하시면 더 적은 코드로 동일한 효과를 낼 수 있답니다.&lt;/p&gt;
&lt;p&gt;예외가 발생하고 나서 그 예외를 처리할 수 있는 예외 처리기를 만날 때까지 스택을 풀어나가면서, C++ 실행 환경은 try
블록부터 생성됐던 모든 자동 객체들에 대해 소멸자를 불러주게 됩니다. 이 과정을 "스택 풀기"라고 합니다. 자동 객체들은
생성됐던 반대 순서로 소멸됩니다.&lt;/p&gt;
&lt;p&gt;이런 원리에 따라 자원을 소유하는 객체들을 자동 객체로 정의하게 되면 예외가 발생하더라도 그런 객체들이 자동적으로 소멸되는
것이지요. 이런 프로그래밍을 가능케 하는 자원 소유 객체들이 파일이나 메모리에 대해 이미 정의되어 있습니다. 파일 자원용으로는
std::fstream을 사용할 수 있고, 메모리 자원용으로는 boost::scoped_ptr을 사용할 수 있습니다.
OpenAndRead()를 다시 한 번 아래와 같이 구현할 수 있을 것입니다.&lt;/p&gt;
&lt;pre&gt;char*
OpenAndRead(const std::string&amp;amp; fn, std::ios_base::openmode mode)
{
  try {
    std::fstream fs(fn.c_str(), mode);
    boost::scoped_ptr&lt;char&gt; buf(new char[BUF_SZ+1]);
    fs.getline(buf.get(), BUF_SZ);
    return buf.get();
  }
  catch (const std::ios_base::failure&amp;amp;) {
    std::cout &amp;lt;&amp;lt; "Can't open or read data from " &amp;lt;&amp;lt; fn &amp;lt;&amp;lt; std::endl;
  }
  catch (const std::bad_alloc&amp;amp;) {
    std::cout &amp;lt;&amp;lt; "Can't allocate memory for data" &amp;lt;&amp;lt; std::endl;
  }
 
  return 0;
}
&lt;/char&gt;&lt;/pre&gt;
&lt;p&gt;C++ 실행기(run-time)가 모든 자원 해제를 알아서 하게 됩니다. 그래서 에러 처리 코드에 자원 해제 코드를 추가할 필요가 없게 됩니다. OpenAndread() 가 상당히 간단해지고, 읽기도 쉬워졌죠?&lt;/p&gt;
&lt;p&gt;예외가 발생하게 되면 C++ 실행기가 예외 처리기를 만날 때까지 소멸자를 역순으로 호출하면서 스택 풀기를 수행할 것입니다.
위 경우에는 동일한 스택 프레임에 예외 처리기가 있고, 두 개의 자동 객체, fs와 buf가 있습니다. 예외 처리기로 제어권이
넘어가기 전에 fs와 buf의 소멸자가 호출될 것이고, 소멸자는 내부 자원을 해제하게 될 것입니다.&lt;/p&gt;
&lt;p&gt;위와 같은 방식은 예외에 대한 반응이 워낙 간단하기 때문에 만족스럽지 않을 거라 생각합니다. 위와 같은 방식으로는
OpenAndRead()의 호출자가 그저 성공 또는 실패 정도만 나타낼 수 있는 정상 포인터 또는 널 포인터를 받을 뿐이기
때문입니다. 호출자 입장에서 생각해 보면, 왜 실패했는지를 알지 못한 상태에서 널 포인터로 할 수 있는 게 없습니다.&lt;/p&gt;
&lt;p&gt;위에서 알 수 있듯이, 에러에 어떻게 반응할지를 결정하는 것이 결함 내성 소프트웨어를 작성하는 데 겪는 또 다른
어려움입니다. 에러가 발생한 상황(context)과 원인이 에러에 대한 반응을 결정하는 데 있어 필수적인 정보라 할 수
있습니다. 그런데 그런 정보들은 여기 저기 흩어져 있기 마련입니다. 에러 처리에는 보통 두가지 부분의 코드가 관련이 있습니다.
하나는 호출자이고 또 하나는 피호출자입니다. 피호출자는 에러가 발생한 원인은 알지만 상황은 잘 모를 가능성이 높고, 반대로, 호출자는 상황은 알지만 이유를 모를 가능성이 높습니다. 이런 상황을 어떻게 극복할 수 있을까요?&lt;/p&gt;
&lt;p&gt;피호출자가 충분한 상황을 알고 있는 호출자에게 최대한 정확히 에러가 발생한 원인을 알려준다면 분명한 해결책이 될 수 있을
것 같습니다. 그렇지만 호출자가 피호출자를 직접 호출한 게 아니었다면 어떻게 될까요? 충분한 상황 정보를 가지고 에러에 대한
반응을 결정할 수 있는 호출자가 에러가 발생한 원인을 정확히 알고 있는 피호출자로부터 멀리 떨어져 있다면, 중간 함수가 에러가
발생한 상세 원인을 무시해 버리고 그냥 성공 또는 실패만을 나타내는 코드를 되돌려 주는 일이 자주 발생합니다. 예제를 통해서
확인해 볼까요?&lt;/p&gt;
&lt;pre&gt;int
OpenAndRead(char* fn, char* mode, char** data)
{
  *data = NULL;
  char* buf = NULL;
  FILE* fp = fopen(fn, mode);
  if (!fp) {
    printf("Can't open %s\n", fn);
    return -1;
  }
 
  buf = malloc(BUF_SZ);
  if (!buf) {
    printf("Can't allocate memory for data\n");
    fclose(fp);
    return -2;
  }
 
  if (!fgets(buf, BUF_SZ, fp)) {
    printf("Can't read data from %s\n", fn);
    free(buf);
    fclose(fp);
    return -3;
  }
 
  *data = buf;
 
  return 0;
}
 
char* foo(char* fn, char* mode)
{
  char* data = 0;
  if (OpenAndRead(fn, mode, &amp;amp;data) &amp;gt;= 0)
    return data;
  else
    return 0;
}
 
void bar()
{
  ...... // fn과 mode를 얻어낸다
  char* data = foo(fn, mode);
  if (data) {
    ...... // 정상 처리
  }
  else {
    ...... // bar()가 뭘 할 수 있을까요?
  }
}
&lt;/pre&gt;
&lt;p&gt;OpenAndRead()는 되돌림 코드(return code)를 통해 에러를 구분하려고 하고 있습니다. 근데 foo()는
그걸 무시하고 그냥 널 포인터나 정상 포인터를 되돌려 주고 마네요. 이래서는 bar()가 진짜 무슨 일이 벌어지고 있는지 알아낼
수가 없게 되고, 널 포인터로는 뭔가 할 수 있는 게 없어집니다. 아마도 bar()가 할 수 있는 거라곤 에러 메시지를 출력하고
그냥 종료하거나 가능하다면 에러를 무시해 버리는 거겠죠. 호출 경로 상의 각 함수들은 어떻게든 에러 처리에 관여할 수 밖에 없기
때문에 예외가 없이는 이런 상황이 더 심각해 질 수 밖에 없습니다. 어떤 함수 작성자는 되돌림 코드가 뭘 의미하지 모를 수도
있고, 에러가 뭘 의미하는지 별로 상관하지 않을 수도 있고, 아니면 충분한 상황을 알지 못해 어떤 처리를 해야할지 결정을 못할
수 있습니다. 그래서 호출 경로 상의 어딘가에서 되돌림 에러 코드가 그냥 실패를 나타내는 값으로 바뀌어 버리게 되는 거죠.&lt;/p&gt;
&lt;p&gt;예외를 사용한다면 이런 문제를 해결할 수 있습니다. 호출 경로상의 어떤 함수가 예외를 처리하지 못하겠다면 그 함수는 그냥 예외를 잡지(catch) 말고 무시해 버리면 됩니다. 진짜 처리할 수 있는 예외만 처리하면 되는 것이지요.&lt;/p&gt;
&lt;p&gt;자~ 이제 마지막으로 한번 만 더 OpenAndRead()를 변형시켜 보겠습니다. 일단 OpenAndRead()와 foo()는 예외를 어떻게 처리해야 할지 모른다고 가정하고, bar()는 처리할 수 있다고 가정해 보겠습니다.&lt;/p&gt;
&lt;pre&gt;char*
OpenAndRead(const std::string&amp;amp; fn, std::ios_base::openmode mode)
{
  std::fstream fs(fn.c_str(), mode); // std::ios_base::failure() 가 발생할지 모릅니다.
  boost::scoped_ptr&lt;char&gt; buf(new char[BUF_SZ+1]);  // std::bad_alloc() 가 발생할지 모릅니다
  fs.getline(buf.get(), BUF_SZ);
  return buf.get();
}
 
char* foo(char* fn, char* mode)
{
  // 아무런 예외도 잡지 않고 있습니다
  return OpenAndRead(fn, mode);
}
 
void bar()
{
  ...... // fn과 mode를 알아냅니다
  try {
    char* data = foo(fn, mode);
  }
  catch (const std::ios_base::failure&amp;amp;) {
    std::cout &amp;lt;&amp;lt; "Can't open or read data from " &amp;lt;&amp;lt; fn &amp;lt;&amp;lt; std::endl;
    // 왜 fn 열어서 데이터를 읽으려고 했는지를 안다면 좀 더 정확한 진단 메시지를 출력하고,
    // 사용자에게 뭔가 조치를 취하라고 알려줄 수 있습니다
  }
  catch (const std::bad_alloc&amp;amp;) {
    std::cout &amp;lt;&amp;lt; "Can't allocate memory for data" &amp;lt;&amp;lt; std::endl;
    // 이런 경우를 대비해 메모리를 미리 따로 마련해 놓았다면 bad_alloc()를 
    // 좀 더 부드럽게 처리할 수도 있을 것입니다.
  }
}
&lt;/char&gt;&lt;/pre&gt;
&lt;p&gt;위 코드에서 볼 수 있듯이, OpenAndRead()와 foo()가 다시 간단해 졌고, bar()만 에러 처리에 관여하고
있습니다. 게다가 예외가 뭘 의미하는지 알고 충분한 상황 정보기 있기 때문에 예외를 정말 절 처리할 수 있게 됐습니다.&lt;/p&gt;
&lt;p&gt;예외의 또 한 가지 장점은 예외는 그 자체로서 객체라는 것입니다. 이건 예외를 발생시킬 때 될 수 있으면 많은 정보를
담아서 발생시킬 수 있다는 것입니다. 다시 말해 예외는 되돌림 코드보다 훨씬 표현력이 좋다고 할 수 있습니다. 그렇다면, 예외
처리기는 그 정보들을 접근할 수 있게 되고, 그 정보들은 어떤 일이 벌어지고 있는지를 정확히 알아내는 데 큰 도움이 될 것입니다.&lt;/p&gt;
&lt;p&gt;이제 여러분에게 "C++ 예외를 사용하고 싶으세요"라고 묻고 싶군요. 뭐라고 답변하시겠어요? "당연히 써야죠"라는 답변을 들었으면 하네요.&lt;/p&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-368-0" class="entry-ccl-by" src="http://cfs.tistory.com/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;img id="ccl-icon-368-1" class="entry-ccl-nc" src="http://cfs.tistory.com/static/admin/editor/ccl_black02.png" alt="비영리"/&gt;
	&lt;img id="ccl-icon-368-2" class="entry-ccl-nd" src="http://cfs.tistory.com/static/admin/editor/ccl_black03.png" alt="변경 금지"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-nc-nd/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-nc-nd/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=4290741" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/agJ7vyZqtRY" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/368</guid>
			<comments>http://yesarang.tistory.com/368#entry368comment</comments>
			<pubDate>Fri, 25 Sep 2009 23:59:16 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/368</feedburner:origLink></item>
		<item>
			<title>위키 업데이트 상황</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/YrB6zrQYKaE/367</link>
			<description>얼마전에 제가 &lt;a title="[http://yesarang.tistory.com/365]로 이동합니다." target="_blank" href="http://yesarang.tistory.com/365"&gt;블로그 글들 옮깁니다&lt;/a&gt;라는 글에서 소프트웨어 개발 관련 글들을 위키로&amp;nbsp; 차례 차례 옮길 것이라고 공지를 드렸습니다. 그 이후에 짬이 나는 대로 옮기고 있는데, 블로그와 위키와의 차이점 때문에 그것도 그리 쉬운 것만은 아니네요. 일일이 하나씩 옮겨야 하니... 암튼 지금까지는 13개의 글을 옮겼습니다.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-stl-auto-ptr-1"&gt;auto_ptr 템플릿 클래스 소개(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-stl-auto-ptr-2"&gt;auto_ptr 의 두 얼굴(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-stl-auto-ptr-3"&gt;auto_ptr을 표준 컨테이너에 담지 말라(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-fundamentals-new-delete"&gt;new와 delete(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-fundamentals-bool"&gt;기본기 다지기, bool type에 관하여(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-fundamentals-explicit"&gt;기본기 다지기, explicit 키워드(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-fundamentals-this"&gt;객체 자신을 가리키는 변수가 this 포인터인 이유는?(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-fundamentals-temporaries-1"&gt;임시 객체는 임시 객체일 뿐 No.1(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-fundamentals-temporaries-2"&gt;임시 객체는 임시 객체일 뿐 No.2(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-fundamentals-temporaries-3"&gt;임시 객체가 충분히 임시스럽기 위하여(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-fundamentals-do-not-copy"&gt;내 객체 복사하지마!(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensw.wikidot.com/cpp-tr1-history"&gt;TR1 History(Korean)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
어떻게 옮기고 있는지 궁금하신 분들은 한 번 들러보시기 바랍니다.&lt;br /&gt;
&lt;br /&gt;
글 옮기는 거 외에도 한번 &lt;a title="[http://opensw.wikidot.com/cpp-fundamentals-exception]로 이동합니다." target="_blank" href="http://opensw.wikidot.com/cpp-fundamentals-exception"&gt;Why Exceptions?&lt;/a&gt;라는 제목으로 C++ exception을 쓰면 어떤 점이 좋은지에 대해 영어로 글을 써 봤습니다. 영어 잘 한다고 자랑하려는 건 아니구요(어차피 잘하지도 못하지만), 국내에만 머무르는 사람이 되지 않기 위해 영어로 작성해 보고 있습니다.  영어에 자신 있으신 분들은 여기에 한글 번역된 것을 올리기 전에 먼저 읽어 보시고 Comment 주시면 감사하겠습니다.&lt;br /&gt;
&lt;br /&gt;
위키 주소는 &lt;a title="[http://opensw.wikidot.com]로 이동합니다." target="_blank" href="http://opensw.wikidot.com"&gt;http://opensw.wikidot.com&lt;/a&gt; 입니다. 많은 관심과 격려 부탁드립니다. ^^&lt;br /&gt;
&lt;br /&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-367-0" class="entry-ccl-by" src="http://cfs.tistory.com/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;img id="ccl-icon-367-1" class="entry-ccl-nc" src="http://cfs.tistory.com/static/admin/editor/ccl_black02.png" alt="비영리"/&gt;
	&lt;img id="ccl-icon-367-2" class="entry-ccl-nd" src="http://cfs.tistory.com/static/admin/editor/ccl_black03.png" alt="변경 금지"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-nc-nd/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-nc-nd/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=4259219" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/YrB6zrQYKaE" height="1" width="1"/&gt;</description>
			<category>기타</category>
			<category>영어</category>
			<category>위키</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/367</guid>
			<comments>http://yesarang.tistory.com/367#entry367comment</comments>
			<pubDate>Tue, 22 Sep 2009 23:27:56 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/367</feedburner:origLink></item>
		<item>
			<title>미투데이 대 트위터</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/XtK6gs_ZtRM/366</link>
			<description>&lt;DIV class=me2day_daily_digest&gt;
&lt;UL&gt;
&lt;LI&gt;미투데이와 트위터의 차이점: 미투데이는 초기부터 API를 써서 3rd party 응용을 위한 환경을 조성하긴 했지만 twitter 만큼은 open 하지 못했다. 왜냐면 traffic을 외부로 잘 넘겨주지 않는 내부완결형 구조 특성이 있다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:12:35" rel=bookmark&gt;2009-09-13 11:12:35&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://me2day.net/yesarang/2009/09/13#11:12:35"&gt;트위터는&lt;/A&gt; 140자 제한마저 외부 서비스를 활성화하는데 사용하고 있으나 미투데이는 링크를 표현하기 위한 별도의 방법을 정의했다. 이 때문에 미투데이가 풍부한 내용을 담을 수 있다는 장점이 있지만 에코시스템 창출에는 트위터가 나은 것 같다&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:15:58" rel=bookmark&gt;2009-09-13 11:15:58&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://me2day.net/yesarang/2009/09/13#11:15:58"&gt;물론 미투데이가 훨씬 우리나라 사람들 스타일에 맞는 것 같긴 하다.&lt;/A&gt;&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:16:59" rel=bookmark&gt;2009-09-13 11:16:59&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;그리고, 사진이랑 비디오를 flickr, youtube에 upload 하긴 하지만 in place로 보여주는 점 등이 그 예이다. 3rd party service가 활성화되기 위한 필요 조건이 traffic 분산이 아닐까 생각해 본다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:23:23" rel=bookmark&gt;2009-09-13 11:23:23&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;미투데이는 이제 인기를 끌기 시작했고, 트위터는 이미 사용자가 폭발한 상태이니 지금 시점에서 직접 비교하긴 힘들지만 나중에 어떻게 될까 상당히 궁금해지는 대목이다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:30:06" rel=bookmark&gt;2009-09-13 11:30:06&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;미투데이가 훌륭한 점 중에 하나는 태그가 따로 있다는 것이다. 짧은 글들이라도 모이면 상당히 중요한 정보가 될 수 있는 것인데, 태그가 그 역할을 충실히 해주고 있다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:32:24" rel=bookmark&gt;2009-09-13 11:32:24&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;트위터도 해쉬태그가 있지만 해쉬태그는 영어밖에 안된다는 문제가 있고, 해쉬태그 여러개 주면 글 쓸 공간이 금방 부족해져 버린다. 다른 사람 글에 대해 핑백으로 링크를 달 수 있는 것도 좋은 점 중의 하나이다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:35:02" rel=bookmark&gt;2009-09-13 11:35:02&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;트위터에서는 다른 사람 글도 보이고 자기 생각도 보이고 싶더라도 공간이 부족해서 그렇게 하질 못한다. 결국 원문을 편집하거나 자기 생각은 거의 없이 그냥 RT를 하게 되는 경우가 종종 있다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:36:43" rel=bookmark&gt;2009-09-13 11:36:43&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;다분히 유명인 위주로 다른 사람들은 그저 정보를 확산시키는 매개체로 작용할 가능성이 충분히 있다는 얘기다. 각 개개인의 개성은 몰살되고, 마케팅을 위한 채널 정도로만 악용될 가능성이 충분히 있다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:38:16" rel=bookmark&gt;2009-09-13 11:38:16&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;트위터에서는 친구라는 개념이 없고 팔로워라는 개념이 있는데, 팔로워는 미투데이의 구독개념과 비슷하다고 볼 수 있다. 친구만큼 깊은 관계를 맺고 싶진 않지만, 그 사람이 생성하는 정보에 대해서는 관심이 있다라는 정도라고 할 수 있다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:44:24" rel=bookmark&gt;2009-09-13 11:44:24&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;물론 때에 따라서는 팔로워가 친구만큼 가까운 관계인 경우도 있지만, 아주 실리적으로 관계를 맺는 약한 관계라고 할 수 있다. 미투데이 친구는 상호간에 관계를 맺지만, 트위터는 한쪽에서 일방적으로 팔로우하면 된다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:46:40" rel=bookmark&gt;2009-09-13 11:46:40&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;그래서 그런지 트위터 내에서는 하루에도 수많은 사람들이 팔로우를 했다가 얼마있다가 언팔로우를 했다가 하는 일이 비일비재하다. 그렇게 별 이유없이 팔로우는 하는 사람들은 대부분 자기를 팔로우하기를 바라는 마음에서 팔로우를 한다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:48:04" rel=bookmark&gt;2009-09-13 11:48:04&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;트위터 내에서는 팔로워의 수가 기본적인 영향력의 지수가 될 수 있고, 영향력이 높다는 얘기는 마케팅 효과가 크다는 얘기가 될 수 있다. 그래서 트위터 내에서는 매일 매일 자신의 팔로워 수를 높이려는 사람들이 무차별적으로 팔로우를 한다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:50:07" rel=bookmark&gt;2009-09-13 11:50:07&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;물론 기존에 이미 유명했던 사람들은 굳이 팔로우를 하지 않지만 유명하지 않았던 사람들이 자신의 영향력을 높이기 위해 그렇게 하고 있다는 것이다. 그렇게 되면 아마도 기업 마케팅 부서에서 연락을 해 올 가능성이 높을 것이기 때문이다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:52:39" rel=bookmark&gt;2009-09-13 11:52:39&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;이런 무차별적이고 실용적인 관계가 과연 요즘과 같은 주목경제에서 효과를 발휘할 수 있을지는 의문이다. 정보의 홍수 속에서 차라리 기존보다 가까운 지인들의 영향력이 커질 수 있는데, 약한 관계를 바탕으로 한 마케팅이 효과를 볼 수 있을지 의문이다.&lt;SPAN class=me2_tags&gt;(2tw 미투데이 트위터 차이점)&lt;/SPAN&gt;&lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2009/09/13#11:54:46" rel=bookmark&gt;2009-09-13 11:54:46&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style="TEXT-ALIGN: right; PADDING-RIGHT: 25px; BACKGROUND: url(http://me2day.net/images/me2day_icon.gif) no-repeat right top; FONT-SIZE: 0.9em"&gt;이 글은 &lt;A href="http://me2day.net/yesarang" target=_blank&gt;김윤수&lt;/A&gt;님의 &lt;A href="http://me2day.net/yesarang/2009/09/13#11:12:35"&gt;2009년 9월 13일&lt;/A&gt;의 미투데이 내용입니다.&lt;/P&gt;&lt;/DIV&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=4176686" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/XtK6gs_ZtRM" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>미투데이</category>
			<category>차이점</category>
			<category>트위터</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/366</guid>
			<comments>http://yesarang.tistory.com/366#entry366comment</comments>
			<pubDate>Sun, 13 Sep 2009 12:12:30 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/366</feedburner:origLink></item>
		<item>
			<title>블로그 글들 옮깁니다.</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/63ssytPzOH0/365</link>
			<description>안녕하세요. 제 블로그를 아껴주시는 독자여러분.&lt;br /&gt;
&lt;br /&gt;아주 오랫동안 블로그를 버려 두다 시피하여 이젠 많은 분들이 관심을 잊어 버렸을 것 같기도 합니다만, 그럼에도 불구하고 여전히 구독해지 않고 기다려 주신분들께 우선 감사의 말씀드립니다.&lt;br /&gt;
&lt;br /&gt;제 글의 성격상 블로그라는 미디어의 형식에 어울리지 않는 것 같아 앞으로는 개발 관련 글들은 블로그에 작성하지 않고 위키 서비스에 올릴 생각입니다. 위키 서비스를 검색하던 차에 wikidot.com 이라는 괜찮은 서비스를 찾아서 여기 있는 글들을 차츰 차츰 옮길 생각입니다. 물론 여기에도 그대로 놔두긴 하겠지만 글들을 검토하면서 좀 더 다듬고 하는 것은 위키에서만 하게 될 것 같습니다.&lt;br /&gt;
&lt;br /&gt;아직은 이제 막 싸이트를 개설하고 위키 문법 공부하고 있는 중이라 글을 본격적으로 옮기진 못했구요. 앞으로 짬 날때마다 옮길 생각입니다.&lt;br /&gt;
&lt;br /&gt;위키 싸이트는 전 세계의 좀 더 많은 분들 소통하기 위해 한글과 영문 두 언어로 작성할 생각입니다.&lt;br /&gt;
&lt;br /&gt;위키 사이트 주소는&amp;nbsp;&amp;nbsp;&lt;A href="http://opensw.wikidot.com/"&gt;http://opensw.wikidot.com&lt;/A&gt; 입니다. 많은 관심 부탁드립니다.&lt;br /&gt;
&lt;br /&gt;어느 정도 글들을 옮긴 이후에 다시 공지드리도록 하겠습니다.&lt;br /&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-365-0" class="entry-ccl-by" src="http://cfs.tistory.com/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;img id="ccl-icon-365-1" class="entry-ccl-nc" src="http://cfs.tistory.com/static/admin/editor/ccl_black02.png" alt="비영리"/&gt;
	&lt;img id="ccl-icon-365-2" class="entry-ccl-nd" src="http://cfs.tistory.com/static/admin/editor/ccl_black03.png" alt="변경 금지"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-nc-nd/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-nc-nd/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/63ssytPzOH0" height="1" width="1"/&gt;</description>
			<category>기타</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/365</guid>
			<comments>http://yesarang.tistory.com/365#entry365comment</comments>
			<pubDate>Sun, 06 Sep 2009 18:00:01 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/365</feedburner:origLink></item>
		<item>
			<title>C++ 이야기 서른번째: boost::shared_ptr performance</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/2sUeiM9ifHE/364</link>
			<description>최근 제가 진행하던 프로젝트에서 boost::shared_ptr를 상당히 많이 사용해 왔었는데, 성능이 좋게 나오질 않아서 혹시나 해서 오늘 성능을 간단하게 측정해 봤더니 속도 차이가 상당히 많이 나는군요. 성능이 &lt;span style="font-weight: bold; color: rgb(25, 61, 169);"&gt;좀&lt;/span&gt; 느리겠거니 했는데 상상 이상이었습니다.(실은 이 문제 때문에 한바탕 홍역을 치뤘죠. ㅠ.ㅠ)&lt;br /&gt;
&lt;br /&gt;
다음은 테스트 프로그램입니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;$ cat shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#include &amp;lt;boost/shared_ptr.hpp&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;using namespace std;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;using namespace boost;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;class AClass&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void Op() const &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ++i;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int Get() const&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return i;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;private:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mutable int i;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#ifdef SHARED_PTR&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;void Foo(const shared_ptr&amp;lt;AClass&amp;gt;&amp;amp; p)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; p-&amp;gt;Op();&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#elif defined(SHARED_PTR_COPY)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;void Foo(shared_ptr&amp;lt;AClass&amp;gt; p)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; p-&amp;gt;Op();&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#else&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;void Foo(AClass* p)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; p-&amp;gt;Op();&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#endif&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;int&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;main(int argc, char* argv[])&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#if defined(SHARED_PTR) || defined(SHARED_PTR_COPY)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; shared_ptr&amp;lt;AClass&amp;gt; p(new AClass());&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#else&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AClass* p = new AClass();&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#endif&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int maxCnt = 1000000000;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (argc &amp;gt;= 2)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; maxCnt = atoi(argv[1]);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; maxCnt; ++i)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Foo(p);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; p-&amp;gt;Get() &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이 테스트 프로그램은 세 가지 경우를 테스트하기 위한 것입니다.&lt;br /&gt;
&lt;br /&gt;
1. raw pointer를 사용하는 경우: SHARED_PTR&amp;nbsp; 또는 SHARED_PTR_COPY 가 정의되지 않은 경우입니다.&lt;br /&gt;
2. shared_ptr을 사용하는 경우: SHARED_PTR 이 정의된 경우입니다. Foo()를 호출할 때, const shared_ptr reference를 넘기기 때문에 복사가 일어나질 않습니다.&lt;br /&gt;
3. shared_ptr을 쓰면서 복사를 하는 경우: SHARED_PTR_COPY가 정의된 경우입니다. Foo()를 호출할 때, shared_ptr 객체를 넘기기 때문에 복사가 한 번 발생하고 이때, shared_ptr의 복사 생성자가 수행되면서 내부적으로 reference count를 증가시키고, 다시 함수에서 리턴될 때, reference count를 감소시키게 됩니다. 그리고 reference count 증가 및 감소는 보통 atomic operation으로 수행되기 때문에 보통의 증가/감소보다는 속도가 느린 걸로 알고 있습니다.&lt;br /&gt;
&lt;br /&gt;
이 세가지에 대해 컴파일러 최적화 옵션 및 BOOST 옵션을 약간 달리 하면서 실행을 해 보았습니다. 다음은 테스트를 위한 Makefile 입니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;$ cat Makefile&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;all: shared1 shared2 shared3 shared_copy1 shared_copy2 shared_copy3 plain1 plain2 plain3&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#CFLAGS=-pg -g&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#LDFLAGS=-pg -g&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;# CASE #1&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;CFLAGS1=&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;# CASE #2&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;CFLAGS2=-O3&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;# CASE #3&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;CFLAGS3=-O3 -DBOOST_SP_DISABLE_THREADS&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;LDFLAGS=&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared1: shared1.o&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(LDFLAGS) -o shared1 shared1.o&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared_copy1: shared_copy1.o&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(LDFLAGS) -o shared_copy1 shared_copy1.o&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;plain1: plain1.o&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(LDFLAGS) -o plain1 plain1.o&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared1.o: shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(CFLAGS1) -c -o shared1.o -DSHARED_PTR shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared_copy1.o: shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(CFLAGS1) -c -o shared_copy1.o -DSHARED_PTR_COPY shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;plain1.o: shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(CFLAGS1) -c -o plain1.o -DPLAIN shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared2: shared2.o&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(LDFLAGS) -o shared2 shared2.o&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared_copy2: shared_copy2.o&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(LDFLAGS) -o shared_copy2 shared_copy2.o&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;plain2: plain2.o&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(LDFLAGS) -o plain2 plain2.o&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared2.o: shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(CFLAGS2) -c -o shared2.o -DSHARED_PTR shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared_copy2.o: shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(CFLAGS2) -c -o shared_copy2.o -DSHARED_PTR_COPY shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;plain2.o: shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(CFLAGS2) -c -o plain2.o -DPLAIN shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared3: shared3.o&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(LDFLAGS) -o shared3 shared3.o&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared_copy3: shared_copy3.o&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(LDFLAGS) -o shared_copy3 shared_copy3.o&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;plain3: plain3.o&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(LDFLAGS) -o plain3 plain3.o&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared3.o: shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(CFLAGS3) -c -o shared3.o -DSHARED_PTR shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared_copy3.o: shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(CFLAGS3) -c -o shared_copy3.o -DSHARED_PTR_COPY shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;plain3.o: shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; g++ $(CFLAGS3) -c -o plain3.o -DPLAIN shared.cpp&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;test: test1 test2 test3&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;test1: shared1_test shared1_copy_test plain1_test&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared1_test: shared1&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time ./shared1 $(CNT)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared1_copy_test: shared_copy1&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time ./shared_copy1 $(CNT)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;plain1_test: plain1&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time ./plain1 $(CNT)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;test2: shared2_test shared2_copy_test plain2_test&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared2_test: shared2&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time ./shared2 $(CNT)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared2_copy_test: shared_copy2&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time ./shared_copy2 $(CNT)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;plain2_test: plain2&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time ./plain2 $(CNT)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;test3: shared3_test shared3_copy_test plain3_test&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared3_test: shared3&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time ./shared3 $(CNT)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;shared3_copy_test: shared_copy3&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time ./shared_copy3 $(CNT)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;plain3_test: plain3&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time ./plain3 $(CNT)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;clean:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rm -rf *.o *.dSYM shared1 shared2 shared3 shared_copy1 shared_copy2 shared_copy3 plain1 plain2 plain3 core* gmon.*&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
1. 테스트 케이스 1: 컴파일러 옵션으로 아무것도 주지 않을 경우 --&amp;gt; CFLGAS1 사용&lt;br /&gt;
2. 테스트 케이스 2: 컴파일러 옵션으로 -O3 를 준 경우 --&amp;gt; CFLAGS2 사용&lt;br /&gt;
3. 테스트 케이스 3: 컴파일러 옵션으로 -O3 -DBOOST_SP_DISABLE_THREADS 사용. BOOST_SP_DISABLE_THREADS를 켜면 reference count 값을 변경시킬 때, atomic operation을 사용하지 않게 됩니다.&lt;br /&gt;
&lt;br /&gt;
이렇게 테스트 프로그램을 작성하고, 테스트를 해 봤더니 다음과 같은 결과가 나오더군요.&lt;br /&gt;
&lt;br /&gt;
$ make&lt;br /&gt;
$ make test&lt;br /&gt;
time ./shared1 1000000000&lt;br /&gt;
1000000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 15.66 real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 15.52 user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.04 sys&lt;br /&gt;
time ./shared_copy1 1000000000&lt;br /&gt;
1000000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 93.33 real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 92.58 user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.24 sys&lt;br /&gt;
time ./plain1 1000000000&lt;br /&gt;
1000000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8.54 real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8.48 user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.02 sys&lt;br /&gt;
time ./shared2 1000000000&lt;br /&gt;
1000000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.81 real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.79 user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00 sys&lt;br /&gt;
time ./shared_copy2 1000000000&lt;br /&gt;
1000000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 37.86 real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 37.62 user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.08 sys&lt;br /&gt;
time ./plain2 1000000000&lt;br /&gt;
1000000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.66 real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.66 user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00 sys&lt;br /&gt;
time ./shared3 1000000000&lt;br /&gt;
1000000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.84 real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.79 user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00 sys&lt;br /&gt;
time ./shared_copy3 1000000000&lt;br /&gt;
1000000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5.74 real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5.70 user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.01 sys&lt;br /&gt;
time ./plain3 1000000000&lt;br /&gt;
1000000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.66 real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.66 user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00 sys&lt;br /&gt;
&lt;br /&gt;
(위 테스트는 looping overhead, function call overhead 를 정확히 측정하지 않았기 때문에 아주 정확한 수치라고는 주장할 수 없음을 미리 밝힙니다. 정확한 수치를 알아내기 위해서는 좀 더 잘 설계된 테스트 케이스를 사용해야 할 것입니다. 다만 위 테스트 결과를 사용하더라도 이 글에서 주장하고자 하는 바를 위한 충분한 근거가 되리라고 생각합니다.)&lt;br /&gt;
&lt;br /&gt;
우선 테스트 케이스1와 테스트 케이스2, 테스트 케이스 3에서 공히 shared_copy &amp;gt; shared &amp;gt; plain 결과가 나온다는 걸 확인할 수 있습니다. BOOST_SP_DISABLE_THREADS 를 켜게 되면 shared_copy에만 영향을 미친다는 걸 알 수 있습니다. 이건 아까 말씀드린 대로 atomic operation이 disable되기 때문인 것으로 추측됩니다. 이상 결과로 보건대 shared_ptr을 쓰실 때는 다음과 같은 점에 유의하셔야 할 것 같습니다.&lt;br /&gt;
&lt;br /&gt;
1.&amp;nbsp; No free lunch. 좋은 게 있으면 그에 대한 비용이 있기 마련이라는 것이죠. shared_ptr는 일반 포인터에 비해 overhead가 있다는 점을 염두해 두셔야겠습니다.&lt;br /&gt;
2. 단순 접근하는 overhead도 2.81/0.66(테스트 케이스 2)으로 상당합니다.&lt;br /&gt;
3. 복사 생성자 overhead는 37.86/0.66(테스트 케이스 2)으로 더 크다는 것을 확인할 수 있습니다. BOOST_SP_DISABLE_THREADS를 켜더라도 5.74/0.66으로 여전히 크다는 것을 알 수 있습니다. 따라서 될 수 있으면 복사를 shared_ptr도 복사는 피하셔야 하겠습니다.&lt;br /&gt;
&lt;br /&gt;
제가 테스트한 환경은 다음과 같습니다.&lt;br /&gt;
&lt;br /&gt;
$ uname -a&lt;br /&gt;
Darwin MyMac.local 9.7.0 Darwin Kernel Version 9.7.0: Tue Mar 31 22:52:17 PDT 2009; root:xnu-1228.12.14~1/RELEASE_I386 i386&lt;br /&gt;
$ g++ --version&lt;br /&gt;
i686-apple-darwin9-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5564)&lt;br /&gt;
&lt;br /&gt;
여러분 환경에서는 어떤 결과가 나오는지 실험해 보시고, 트랙백 한 번 남겨 주시면 감사하겠습니다. ^^&lt;br /&gt;
&lt;br /&gt;
소스 코드 첨부합니다(looping overhead를 측정하기 위해 본문 소스에서 약간 더 수정했습니다).&lt;br /&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://yesarang.tistory.com/attachment/cfile22.uf@124D160C4A462A3E54D0C9.gz"&gt;&lt;img src="http://cfs.tistory.com/blog/image/extension/gz.gif" alt="" style="vertical-align: middle;" /&gt; shared.tar.gz&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=3521970" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/2sUeiM9ifHE" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<category>boost shared_ptr performance</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/364</guid>
			<comments>http://yesarang.tistory.com/364#entry364comment</comments>
			<pubDate>Sun, 28 Jun 2009 13:44:49 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/364</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2009년 1월 22일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/0efh8MqBtOU/363</link>
			<description>&lt;div class="me2day_daily_digest"&gt;&lt;ul&gt;&lt;li&gt;&lt;a href='http://me2day.net/kss/2009/01/22#17:07:15'&gt;개발자를 위한 글꼴! 나눔고딕_코딩 글꼴 공개!&lt;/a&gt; 우왕 멋집니다. 감동입니다. 바로 &lt;a href='http://dev.naver.com/projects/nanumfont/download'&gt;다운로드&lt;/a&gt; 들어가야 함다.&lt;span class="me2_tags"&gt;(네이버 폰트공개 나눔고딕코딩)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2009/01/22#17:41:04" rel="bookmark" title="퍼머링크" class="datetime"&gt;2009-01-22 17:41:04&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 &lt;a href="http://me2day.net/yesarang/2009/01/22#17:41:04"&gt;2009년 1월 22일&lt;/a&gt;의 미투데이 내용입니다.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/0efh8MqBtOU" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>나눔고딕코딩</category>
			<category>네이버</category>
			<category>폰트공개</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/363</guid>
			<comments>http://yesarang.tistory.com/363#entry363comment</comments>
			<pubDate>Fri, 23 Jan 2009 04:33:07 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/363</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2009년 1월 4일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/djm2S9jExHQ/362</link>
			<description>&lt;div class="me2day_daily_digest"&gt;&lt;ul&gt;&lt;li&gt;I'm back!&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2009/01/04#01:08:35" rel="bookmark" title="퍼머링크" class="datetime"&gt;2009-01-04 01:08:35&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 &lt;a href="http://me2day.net/yesarang/2009/01/04#01:08:35"&gt;2009년 1월 4일&lt;/a&gt;의 미투데이 내용입니다.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/djm2S9jExHQ" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/362</guid>
			<comments>http://yesarang.tistory.com/362#entry362comment</comments>
			<pubDate>Tue, 06 Jan 2009 04:34:55 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/362</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 12월 24일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/6i7zjCcEYfw/361</link>
			<description>&lt;div class="me2day_daily_digest"&gt;&lt;ul&gt;&lt;li&gt;Merry Christmas &amp; Happy New Year! 전 11일 장기 휴가 돌입합니다. 저 없는 동안 잘 지내세요~ 인터넷 접속 안하기 한 번 실천해 봐야겠습니다.&lt;span class="me2_tags"&gt;(인터넷생활)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/12/24#18:09:36" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-12-24 18:09:36&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 &lt;a href="http://me2day.net/yesarang/2008/12/24#18:09:36"&gt;2008년 12월 24일&lt;/a&gt;의 미투데이 내용입니다.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/6i7zjCcEYfw" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>인터넷생활</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/361</guid>
			<comments>http://yesarang.tistory.com/361#entry361comment</comments>
			<pubDate>Thu, 25 Dec 2008 04:32:32 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/361</feedburner:origLink></item>
		<item>
			<title>C++이야기 스물아홉번째: Portable C++ Timer Class #2</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/j17uXwtcsKY/360</link>
			<description>If you are an English speaker, then follow this link.&lt;br /&gt;
&lt;a target="_blank" href="http://codeguru.textcube.com/3" title="Permalink"&gt;C++ Tips 29th: Portable C++ Timer Class #2&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;이번에는 timer 관련 클래스들에 어떤 멤버 함수와 멤버 변수를 정의해야할지에 대해 자세히 알아보겠습니다. 사용자가 가장 많이 사용하게될 클래스는 TimerDriver일테니 이것부터 시작해 보도록 하겠습니다.&lt;br /&gt;
&lt;br /&gt;
저번글에서 말씀드렸던 것처럼 TimerDriver는 &lt;strong&gt;&lt;font color="#3058d2"&gt;등록된 &lt;/font&gt;&lt;/strong&gt;타이머들이 정확한 시간에 expire되도록 해주는 클래스입니다. 이점을 고려하면 타이머 인스턴스들을 등록하고 등록해제하는 멤버 함수는 누가 봐도 필요할 것 같습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: courier new,courier,monospace;"&gt;class TimerDriver {&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;public:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; TimerId RegisterTimer(const Timer&amp;amp; t);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; void UnregisterTimer(TimerId tid);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이 인터페이스를 정의하고 나면 등록된 타이머 인스턴스들을 저장해 놓을 저장 공간이 필요하다는 걸 금방 알게 됩니다. 그럼 어떤 데이터 구조가 저장 공간으로 적당할까요? 가장 적당한 데이터 구조를 택하려면 아무래도 사용자가 TimerDriver를 사용하는 패턴을 먼저 알아야 할 것 같습니다.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;지금까지 정의한 멤버 함수는 RegisterTimer(), UnregisterTimer() 두 개가 있고, 이 둘은 결국 &lt;span style="color: rgb(48, 88, 210); font-weight: bold;"&gt;삽입과 삭제&lt;/span&gt;에 해당합니다. 그리고 타이머 인스턴스들 &lt;span style="color: rgb(48, 88, 210); font-weight: bold;"&gt;하나 하나를 건드리면서&lt;/span&gt; 드라이브 할 수 있습니다. 그렇지만 사용자가 정렬된 타이머 리스트를 필요로 하거나, 타이머 인스턴스를 직접 접근하거나, 타이머 인스턴스를 상당히 빠르게 검색해야할 필요성은 없을 것입니다.&lt;/p&gt;
&lt;p&gt;그래서 저는 std::list가 등록된 타이머 인스턴스 저장 데이터 구조로 가장 적당하다고 생각합니다.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight: bold; color: rgb(0, 47, 255); font-family: courier new,courier,monospace;"&gt;#include &amp;lt;list&amp;gt;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class Timer;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class TimerDriver {&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;public:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; TimerId RegisterTimer(const Timer&amp;amp; t);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; void UnregisterTimer(TimerId tid);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;private:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(0, 47, 255); font-family: courier new,courier,monospace;"&gt;std::list&amp;lt;Timer&amp;gt; timer_list_;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;다음으로 RegisterTimer() 와 UnregisterTimer()의 입력 인자와 리턴값에 대해 생각해 보겠습니다.&lt;/p&gt;
&lt;p&gt;제가 RegisterTimer()의 리턴값과 UnregisterTimer()의 입력인자로 TimerId라는 타입을 도입했습니다. 'TimerId' 타입의 필요성은 분명해 보이는데... 어떤식으로 'TimerId' 타입을 정의해야할까요? TimerDriver가 내부적으로 식별자 풀(identifier pool)을 관리해야할까요 아니면 TimerId가 그냥 Timer*이면 될까요? 식별자 풀을 관리한다면 각 타이머 인스턴스에 할당된 식별자는 어디에 저장해야할까요? timer_list_는 list&amp;lt;Timer&amp;gt;라고 선언해도 무방할까요 아니면 다른 뭔가로 선언해야할까요? 예를 들어, list&amp;lt;Timer*&amp;gt;와 같이 말이죠. 우리가 결론에 도달할 때까지는 이런 수 많은 질문들이 머리속을 맴돌게 됩니다. 혼란 그 자체죠? 이런 간단한 클래스를 설계하는데도 말입니다.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;그렇지만, 소프트웨어 개발자로서 선택에 대한 분명한 이유를 찾아가며 이런 혼란스러움을 해결해 가야 합니다. 삶이란 게 문제로 가득차 있고, 산다는 것 자체가 해답을 찾아가는 과정 아닐까요? 그러니 너무 괴로워하지 마시고 맘을 가다듬어 보시죠. 사실 이 모든 문제들이 서로 연결되어 있습니다. 한 문제에 대한 해결책을 찾게 되면... 짠! 하고 다른 모든 문제들에 대한 해결책도 찾을 수 있게 될테니까요.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;그럼 문제점을 하나씩 해결해 보시죠. 숨을 기~~~~~~~~~~~~~피 들이 쉬시고~~~&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;TimerId! TimerDriver가 식별자 풀을 관리해야할까요? 가능한 해결책이죠. 사용자가 RegisterTimer()를 호출하여 타이머 인스턴스를 등록해달라고 하면 TimerDriver가 식별자 풀에서 할당되지 않은 ID를 새로 등록할 타이머 인스턴스에 할당할 수 있을 것입니다. 그리고, 나중에 UnregisterTimer()를 호출했을 때, 삭제하려면 할당된 그 ID를 어딘가에 저장해야 합니다.&lt;/p&gt;
&lt;p&gt;그런데 저는 정말 식별자 풀을 관리하고 싶지는 않네요. 현재 요구사항에 비해 너무 복잡한 해결책이거든요. 저는 간단한 해결책을 훨씬 선호합니다. 그렇게 하면 코드량도 적어지고, 버그고 적어질 테니까요. 그래서 식별자 풀은 설계 대안에서 제외하기로 했습니다. 그럼 다른 대안이 있을까요? TimerId를 그냥 Timer*로 선언하면 어떨까요?&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;#include &amp;lt;list&amp;gt;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class Timer;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="color: rgb(0, 47, 255); font-weight: bold; font-family: courier new,courier,monospace;"&gt;typedef Timer* TimerId;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class TimerDriver {&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;public:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="font-weight: bold; color: rgb(0, 47, 255);" class="copyAngel_codeguru_LinkUp" original="http://codeguru.textcube.com/3" entryid="3"&gt;TimerId&lt;span class="copyAngel_codeguru_LinkUp_local" style="display: none;"&gt;TimerId&lt;/span&gt;&lt;/span&gt;

 RegisterTimer(const Timer&amp;amp; t);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; void UnregisterTimer(TimerId tid);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;private:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; std::list&amp;lt;Timer&amp;gt; timer_list_;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이렇게 하면 식별자 풀을 관리하지 않아도 되고, RegisterTimer() 는 리턴값으로 &amp;amp;t를 리턴하면 되니 구현이 간단해 질 것입니다. 그럼, 거의 완벽한 해결책을 찾은 거네요. 그죠? 워!워!워! 그렇게 쉽게 해결될 리가 있나요. 조금만 더 깊이 생각해 보시죠.&lt;/p&gt;
&lt;p&gt;그냥 TimerId를 Timer*로 선언하게 되면 타이머 인스턴스의 내부 표현 방식을 사용자가 직접 다루게 되고, 결국 이것은 encapsulation rule을 위배하게 됩니다. 그렇게 할 경우, TimerDriver가 타이머 인스턴스 내부 표현 방식을 바꾸게 되면 TimerId가 Timer*라는 거를 가정하고 짠 사용자 코드는 다 작동하지 않게 될 것입니다. 그래서 저는 TimerId를 그냥 void*로 선언하려고 합니다. 그럼 사용자는 타미어 인스턴스 내부 표현 방식이 어떻게 되는지 전혀 알 수가 없겠지요.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;#include &amp;lt;list&amp;gt;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class Timer;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="color: rgb(0, 47, 255); font-weight: bold; font-family: courier new,courier,monospace;"&gt;typedef void* TimerId;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class TimerDriver {&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;public:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; TimerId RegisterTimer(const Timer&amp;amp; t);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; void UnregisterTimer(TimerId tid);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;private:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; std::list&amp;lt;Timer&amp;gt; timer_list_;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;다음으로는 timer_list_ 멤버 변수에 대해 생각해 보겠습니다. 저번 글에서 밝혔다시피 저는 Timer에서 상속받은 PeriodicTimer와 OneShotTimer를 정의하려고 합니다. Timer에는 공통의 인터페이스만 정의하고 PeriodicTimer 와 OneShotTimer에서 그걸 구현하여 &lt;span style="color: rgb(48, 88, 210); font-weight: bold;"&gt;다형성&lt;/span&gt;을 보이게 하려는 것이지요. 그렇다면 timer_list_를 list&amp;lt;Timer*&amp;gt;로 선언해야 할 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;#include &amp;lt;list&amp;gt;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class Timer;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;typedef void* TimerId;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class TimerDriver {&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;public:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; TimerId RegisterTimer(const Timer&amp;amp; t);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; void UnregisterTimer(TimerId tid);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;private:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(0, 47, 255); font-weight: bold; font-family: courier new,courier,monospace;"&gt;std::list&amp;lt;Timer*&amp;gt; timer_list_;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;현재 TimerDriver 인터페이스에는 한 가지 멤버 함수가 빠진 것 같습니다. 보통 사용자는 먼저 타이머들을 등록한 후에 타이머들을 돌리기 시작하겠죠? 그래서 다음과 같이 Run() 멤버 함수를 추가했습니다.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;#include &amp;lt;list&amp;gt;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class Timer;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;typedef void* TimerId;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;class TimerDriver {&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;public:&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="copyAngel_codeguru_LinkUp" original="http://codeguru.textcube.com/3" entryid="3"&gt;TimerId&lt;span class="copyAngel_codeguru_LinkUp_local" style="display: none;"&gt;TimerId&lt;/span&gt;&lt;/span&gt;

 RegisterTimer(const Timer&amp;amp; t);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; void UnregisterTimer(TimerId tid);&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(0, 47, 255); font-weight: bold; font-family: courier new,courier,monospace;"&gt;void Run();&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&lt;span class="copyAngel_codeguru_LinkUp" original="http://codeguru.textcube.com/3" entryid="3"&gt;private:&lt;span class="copyAngel_codeguru_LinkUp_local" style="display: none;"&gt;private:&lt;/span&gt;&lt;/span&gt;

&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; std::list&amp;lt;Timer*&amp;gt; timer_list_;&lt;/span&gt;&lt;br style="font-family: courier new,courier,monospace;"&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이제, 이 정도면 TimerDriver의 인터페이스는 거의 완벽하다고 느껴지네요. 다음글에서 TimerDriver의 구현에 대해 다뤄보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2241387" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/j17uXwtcsKY" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/360</guid>
			<comments>http://yesarang.tistory.com/360#entry360comment</comments>
			<pubDate>Mon, 22 Dec 2008 22:35:29 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/360</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 12월 20일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/o0fcpXgl9j8/359</link>
			<description>&lt;div class="me2day_daily_digest"&gt;&lt;ul&gt;&lt;li&gt;영문 블로그 세번째 글: &lt;a href='http://codeguru.textcube.com/3'&gt;C++ Tips 29th: Portable C++ Timer Class #2&lt;/a&gt;, &lt;a href='http://codeguru.textcube.com/3'&gt;지난 글&lt;/a&gt;을 안 보신 분은 먼저 읽어보시는 센스를 발휘해 주세요&lt;span class="me2_tags"&gt;(블로그 영문)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/12/20#22:20:11" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-12-20 22:20:11&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 &lt;a href="http://me2day.net/yesarang/2008/12/20#22:20:11"&gt;2008년 12월 20일&lt;/a&gt;의 미투데이 내용입니다.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/o0fcpXgl9j8" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>블로그</category>
			<category>영문</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/359</guid>
			<comments>http://yesarang.tistory.com/359#entry359comment</comments>
			<pubDate>Sun, 21 Dec 2008 05:18:08 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/359</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 12월 18일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/q25ouFsnWVQ/358</link>
			<description>&lt;div class="me2day_daily_digest"&gt;&lt;ul&gt;&lt;li&gt;한 동안 블로그에 글 못 올릴 것 같습니다. 양해 바랍니다.&lt;span class="me2_tags"&gt;(블로그 휴업)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/12/18#22:33:52" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-12-18 22:33:52&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 &lt;a href="http://me2day.net/yesarang/2008/12/18#22:33:52"&gt;2008년 12월 18일&lt;/a&gt;의 미투데이 내용입니다.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/q25ouFsnWVQ" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>블로그</category>
			<category>휴업</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/358</guid>
			<comments>http://yesarang.tistory.com/358#entry358comment</comments>
			<pubDate>Fri, 19 Dec 2008 04:32:33 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/358</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 12월 9일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/zSY8wxMdApc/357</link>
			<description>&lt;div class="me2day_daily_digest"&gt;&lt;ul&gt;&lt;li&gt;&lt;a href='http://www.ddj.com/hpc-high-performance-computing/212201163'&gt;Measuring Parallel Performance: Optimizing a Concurrent Queue&lt;/a&gt;: 나중에 꼭 읽어 봐야 겠습니다.&lt;span class="me2_tags"&gt;(인터넷오늘은 북마크 SW개발 hpc thread)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/12/09#00:19:02" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-12-09 00:19:02&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 &lt;a href="http://me2day.net/yesarang/2008/12/09#00:19:02"&gt;2008년 12월 9일&lt;/a&gt;의 미투데이 내용입니다.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/zSY8wxMdApc" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>HPC</category>
			<category>sw개발</category>
			<category>thread</category>
			<category>북마크</category>
			<category>인터넷오늘은</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/357</guid>
			<comments>http://yesarang.tistory.com/357#entry357comment</comments>
			<pubDate>Tue, 09 Dec 2008 04:32:30 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/357</feedburner:origLink></item>
		<item>
			<title>C++이야기 스물아홉번째: Portable C++ Timer Class #1</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/-aia-xs77gc/356</link>
			<description>If you are an English speaker, then follow this link.&lt;br /&gt;
&lt;a target="_blank" href="http://codeguru.textcube.com/2" title="Permalink"&gt;C++ Tips 29th: Portable C++ Timer Class #1&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
우리네 생활이 온통 시간에 둘러쌓여 있듯이, 응용프로그램부터 펌웨어에 이르는 프로그램도 시간에 둘러쌓여 있지요. 예를 들자면, 달력 프로그램은 시간과 연관되어 있는 약속과 할일들을 처리하고, 검색 로봇은 주기적으로 페이지를 긁어 오고, 멀티미디어 재생기는 제 시간에 맞춰서 데이터 저장소로부터 열심히 데이터를 끌어 오고, TCP/IP 위에서 동작하는 통신 미들웨어는 데이터 교환이나 요청한 연산에 대해 타임아웃을 처리하고, 디바이스 드라이버는 주기적으로 디바이스에 상태 체크 요청을 보냅니다.
이렇게 시간은 워낙 근본적인 개념이라 아주 작은 프로그램을 개발하는 경우를 제외한다면 대부분 타임아웃이나 주기적인 이벤트를 처리할 수 있는 라이브러리가 필요하게 됩니다.&lt;br /&gt;
&lt;br /&gt;
그래서 이번과 앞으로 몇 번에 걸쳐 boost 라이브러리를 활용하여 타임아웃이나 주기적인 이벤트를 처리할 수 있는 타이머 클래스를 구현하는 방법에 대해 얘기하려고 합니다.&lt;br /&gt;
&lt;br /&gt;
타이머와 연관된 기본적인 개념을 먼저 한 번 생각해 보죠.
&lt;ol&gt;
&lt;li&gt;타이밍 이벤트는 주기적으로 발생하거나 딱 한 번만 발생한다.&lt;/li&gt;
&lt;li&gt;타이밍 이벤트가 발생하면 특정 작업을 처리해야 한다.&lt;/li&gt;
&lt;li&gt;정확한 시간에 타이밍 이벤트가 발생하도록 해주는 일종의 구동기가 존재한다.&lt;/li&gt;
&lt;/ol&gt;
저는 이 정도 개념이 우선 떠오르네요.&lt;br /&gt;
&lt;br /&gt;
그럼 먼저 첫번째 개념에서 어떤 클래스를 정의해야 하는지부터 시작해 볼까요? 다음과 같이 enum 값들로 두 가지 타입을 다 지원하는 클래스 하나를 정의할 수도 있을 겁니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: courier new,courier,monospace;"&gt;
class Timer {&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp; typedef enum {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; PERIODIC_TIMER,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ONE_SHOT_TIMER&lt;br /&gt;
&amp;nbsp; } Type;&lt;br /&gt;
&lt;br /&gt;
private:&lt;br /&gt;
&amp;nbsp; Type m_type;&lt;br /&gt;
};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
서로 다른 두 개념을 클래스 하나로 묶어 놓은 설계가 과연 좋은 설계일까요? 좀 더 주의깊게 생각해 보시죠. 이 설계대로 하면 생성자는 어떻게 작성해야 할까요?

&lt;p&gt;&lt;span style="font-family: courier new,courier,monospace;"&gt;#include &amp;lt;boost/date_time.hpp&amp;gt; // for time_duration&lt;br /&gt;
&lt;br /&gt;
class Timer {&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp; typedef enum {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; PERIODIC_TIMER,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ONE_SHOT_TIMER&lt;br /&gt;
&amp;nbsp; } Type;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span style="font-weight: bold; color: rgb(0, 30, 161);"&gt;Timer(Type type, const boost::posix_time::time_duration&amp;amp; td);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
private:&lt;br /&gt;
&amp;nbsp; Type m_type;&lt;br /&gt;
};&lt;/span&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;'type' 인자의 의미는 분명하지만, 'td' 인자는 어떤 것을 뜻할까요? 보통 주기적인 이벤트는 주기(== 'td')라는 게 필요하고, 타임아웃 이벤트는 그 이벤트가 발생할 시간(== 현재 시간 + 'td')을 필요로 할테니... 'td' 인자가 뜻하는 바는 'type'에 따라 달라지겠죠? 그렇다면,&amp;nbsp; Timer::Timer() 을 구현한 코드가 아무래도 다음 코드에서 보시는 것처럼 'type' 값에 의존적인 코드가 될 것 같군요.&lt;/p&gt;
&lt;p style="font-family: courier new,courier,monospace;"&gt;Timer::Timer(Type type, const boost::posix_time::time_duration&amp;amp; td)&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp; switch (type)&lt;br /&gt;
&amp;nbsp; {&lt;br /&gt;
&amp;nbsp; case PERIODIC_TIMER:&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ......&lt;br /&gt;
&amp;nbsp; &amp;nbsp; break;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; case ONE_SHOT_TIMER:&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ......&lt;br /&gt;
&amp;nbsp; &amp;nbsp; break;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; default:&lt;br /&gt;
&amp;nbsp; &amp;nbsp; break;&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
}&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;이렇게 되면 새로운 타입의 타이머를 추가할 때마다 이 생성자를 수정해야할 필요가 있다는 건 쉽게 눈치 채실 수 있으시겠죠? 상당히 심각한 유지보수 문제네요. 이것 말고도 다른 문제점들도 있습니다. 세번째 개념에서 드라이버 클래스를 정의할 필요성이 있다는 걸 알 수 있습니다.&lt;/p&gt;
&lt;p style="font-family: courier new,courier,monospace;"&gt;class TimerDriver { ...... };&lt;/p&gt;
&lt;p&gt;TimerDriver가 서로 다른 타입의 타이머 인스턴스들을 제대로 처리하려면 타이머의 타입을 알아야할 것입니다. 그러니 TimerDriver의 구동 멤버 함수는 당연히 타이머의 타입 정보를 필요로 하게 됩니다. 생각이 여기에 이르면 새로운 타입의 타이머를 추가할 때마다 TimerDriver의 구동 멤버 함수도 수정해야 한다는 걸 알 수 있게 됩니다.&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;마지막 문제점으로 주기적인 이벤트는 주기를 저장해야 할테고, 타임아웃 이벤트는 이벤트가 발생해야할 시간을 저장해야 한다는 점이 떠오르네요. 이걸 저장하기 위해 하나의 클래스에 두 개의 멤버 변수를 정의한다면 타이머 인스턴스의 타입에 따라서 낭비되는 공간이 생길 것입니다.&lt;/p&gt;

&lt;p&gt;이상의 문제점을 고려해 보건데, 주기적인 이벤트와 타임아웃 이벤트를 위해 따로 클래스를 정의하는 게 더 좋은 설계라는 게 명백해 보입니다. 그렇지만 한편으로는 TimerDriver는 여전히 이 클래스들을 일관되게 처리할 필요가 있을 것입니다. 따라서 저는 공통의 부모 클래스로 Timer를 두고, 파생 클래스로 PeriodicTimer와 OneShotTimer를 두려고 합니다.&lt;/p&gt;

&lt;p style="font-family: courier new,courier,monospace; font-weight: bold; color: rgb(0, 30, 161);"&gt;class Timer { ...... };&lt;/p&gt;

&lt;p style="font-family: courier new,courier,monospace; font-weight: bold; color: rgb(0, 30, 161);"&gt;class PeriodicTimer : public Timer { ...... };&lt;/p&gt;
&lt;p style="font-family: courier new,courier,monospace; font-weight: bold; color: rgb(0, 30, 161);"&gt;class OneShotTimer : public Timer { ...... };&lt;/p&gt;

그럼 이제 Timer, PeriodicTimer, OneShotTimer 각각 클래스에는 어떤 것들을 정의해야 할까요? 이 문제는 다음 글에서 알아보도록 하겠습니다. ^^&lt;br /&gt;
&lt;br /&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2166883" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/-aia-xs77gc" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/356</guid>
			<comments>http://yesarang.tistory.com/356#entry356comment</comments>
			<pubDate>Mon, 08 Dec 2008 22:37:17 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/356</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 12월 7일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/OW6GHhjHZqg/355</link>
			<description>&lt;div class="me2day_daily_digest"&gt;&lt;ul&gt;&lt;li&gt;&lt;a href='http://codeguru.textcube.com/2'&gt;C++ Tips 29th: Portable C++ Timer Class #1&lt;/a&gt;: 영어 블로그 두번째 글입니다. Wordpress가 너무 꼬져서 textcube.com 으로 옮겨 봤습니다. 일단 tistory랑 비슷해서 편하네요. 이번에는 영문으로 먼저 작성했습니다.&lt;span class="me2_tags"&gt;(블로그 영문)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/12/07#22:47:34" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-12-07 22:47:34&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 &lt;a href="http://me2day.net/yesarang/2008/12/07#22:47:34"&gt;2008년 12월 7일&lt;/a&gt;의 미투데이 내용입니다.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/OW6GHhjHZqg" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>블로그</category>
			<category>영문</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/355</guid>
			<comments>http://yesarang.tistory.com/355#entry355comment</comments>
			<pubDate>Mon, 08 Dec 2008 04:32:09 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/355</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 12월 3일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/OSslMe5Aw3U/354</link>
			<description>&lt;div class="me2day_daily_digest"&gt;&lt;ul&gt;&lt;li&gt;&lt;a href='http://www.youtube.com/watch?v=OCl3M5grVF4'&gt;샴페인-박준규-흑인영어&lt;/a&gt;: ㅋㅋㅋ 배꼽 빠져&lt;span class="me2_tags"&gt;(me2gag)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/12/02#15:35:41" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-12-02 15:35:41&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;a href='http://kr.finance.yahoo.com/news/view?aid=2008120213091740180'&gt;이 기사&lt;/a&gt; 말이 되는 듯… 뭐 꼭 근거가 있는 건 아니고 그냥 느낌이 그렇다는 얘기&lt;span class="me2_tags"&gt;(투자생활 그나저나 예상대로 얼마전 반등은 단기 반등이었을 뿐 언론들은 제발 호들갑 떨지 말아라)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/12/03#00:35:04" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-12-03 00:35:04&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;제가 요즘 관심을 두는 주식들: &lt;a href='http://kr.stock.yahoo.com/sise/st01.html?code=005490'&gt;POSCO&lt;/a&gt;, &lt;a href='http://kr.stock.yahoo.com/sise/st01.html?code=072870'&gt;메가스터디&lt;/a&gt;, &lt;a href='http://kr.stock.yahoo.com/sise/st01.html?code=046890'&gt;서울반도체&lt;/a&gt;, &lt;a href='http://kr.stock.yahoo.com/sise/st01.html?code=066570'&gt;LG전자&lt;/a&gt; 등 입니다.&lt;span class="me2_tags"&gt;(투자생활)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/12/03#00:47:23" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-12-03 00:47:23&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 &lt;a href="http://me2day.net/yesarang/2008/12/02#15:35:41"&gt;2008년 12월 2일&lt;/a&gt;에서 &lt;a href="http://me2day.net/yesarang/2008/12/03#00:47:23"&gt;2008년 12월 3일&lt;/a&gt;까지의 미투데이 내용입니다.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/OSslMe5Aw3U" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>me2gag</category>
			<category>그나저나</category>
			<category>단기</category>
			<category>떨지</category>
			<category>말아라</category>
			<category>반등은</category>
			<category>반등이었을</category>
			<category>뿐</category>
			<category>언론들은</category>
			<category>얼마전</category>
			<category>예상대로</category>
			<category>제발</category>
			<category>투자생활</category>
			<category>호들갑</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/354</guid>
			<comments>http://yesarang.tistory.com/354#entry354comment</comments>
			<pubDate>Wed, 03 Dec 2008 04:32:31 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/354</feedburner:origLink></item>
		<item>
			<title>티스토리 달력 공모전 응모</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/dUcnQDU5_xU/353</link>
			<description>음... 올해 있었던 추억을 담아 응모해 봅니다.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;img src="http://cfs13.tistory.com/image/6/tistory/2008/12/03/01/25/4935618a1164e" alt="" filemime="" filename="IMG_6180.JPG" height="383" width="510"/&gt;&lt;/div&gt;&lt;br /&gt;
여름에 아이들과 함께 동네 야외 수영장 갔을 때 찍었던 사진입니다. 오빠와 동생이 함께 노는 모습이 보기 좋아서 선정해 봤습니다. 7월 사진으로 적당할 것 같네요.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;img src="http://cfs12.tistory.com/image/1/tistory/2008/12/03/01/32/4935631b65928" alt="" filemime="" filename="IMG_6381.JPG" height="383" width="510"/&gt;&lt;/div&gt;&lt;br /&gt;
위 사진은 대관령 양떼 목장에 갔을 때 찍은 하늘 사진입니다. 날씨가 아주 맑은 날이어서 하늘이 너무 멋있어 보이더군요. 9월 사진으로 적당할 것 같네요.&lt;br /&gt;
&lt;br /&gt;
그리고 하늘의 구름과 땅의 양떼가 어우러진 이 사진도 좋은 것 같습니다. 마찬가지로 9월이 적당할 것 같네요.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;img src="http://cfs14.tistory.com/image/33/tistory/2008/12/03/01/35/493563de84443" alt="" filemime="" filename="IMG_6409.JPG" height="301" width="510"/&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2139313" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/dUcnQDU5_xU" height="1" width="1"/&gt;</description>
			<category>기타</category>
			<category>7월</category>
			<category>9월</category>
			<category>사진</category>
			<category>티스토리달력</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/353</guid>
			<comments>http://yesarang.tistory.com/353#entry353comment</comments>
			<pubDate>Wed, 03 Dec 2008 01:36:57 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/353</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 11월 30일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/6PBvRNguA50/352</link>
			<description>&lt;div class="me2day_daily_digest"&gt;
    &lt;ul&gt; 
      &lt;li&gt;
        &lt;a href='http://yesarang.wordpress.com/2008/11/24/cpp-tips-28/'&gt;C++ Tips 28th: Applying STL Algorithms to a Map Container&lt;/a&gt;: It's not that easy to translate a post in Korean to English.
        &lt;span class="me2_tags"&gt;(블로그 영문 첫글)&lt;/span&gt;
        &lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/30#20:22:15" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-30 20:22:15&lt;/a&gt;&lt;/span&gt;
        
      &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;
      이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 
      &lt;a href="http://me2day.net/yesarang/2008/11/30#20:22:15"&gt;2008년 11월 30일&lt;/a&gt;의 
      미투데이 내용입니다.
    &lt;/p&gt;
  &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/6PBvRNguA50" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>블로그</category>
			<category>영문</category>
			<category>첫글</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/352</guid>
			<comments>http://yesarang.tistory.com/352#entry352comment</comments>
			<pubDate>Mon, 01 Dec 2008 04:32:18 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/352</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 11월 28일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/TC1-cbpvH08/351</link>
			<description>&lt;DIV class=me2day_daily_digest&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://www.etnews.co.kr/news/detail.html?id=200811170181&amp;amp;mc=m_012_00005"&gt;스마트폰이 노트북 밀어낸다&lt;/A&gt;: 스마트폰 세상이 오고 있군요. 무선 인터넷 세상도 같이 와야 할텐데 말이죠. &lt;SPAN class=me2_tags&gt;(인터넷오늘은 북마크 스마트폰)&lt;/SPAN&gt; &lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2008/11/27#23:15:03" rel=bookmark&gt;2008-11-27 23:15:03&lt;/A&gt;&lt;/SPAN&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://www.ktwb.co.kr/sub04_u2000.htm"&gt;맥용 와이브로 USB 모뎀&lt;/A&gt;이 있었군요 &lt;SPAN class=me2_tags&gt;(인터넷오늘은 북마크 와이브로 맥)&lt;/SPAN&gt; &lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2008/11/27#23:28:43" rel=bookmark&gt;2008-11-27 23:28:43&lt;/A&gt;&lt;/SPAN&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://kr.finance.yahoo.com/news/view?aid=2008112716291490525"&gt;다음, 부동산정보도 네이버 제쳤다&lt;/A&gt;: 다음이 만년 2등에서 벗어날 수 있을까요? 지금은 너무 많이 차이가 나서… 다음이 좀 더 잘해준다면 선의의 경쟁이 될 수 있을텐데요 &lt;SPAN class=me2_tags&gt;(인터넷오늘은 북마크 다음 전 네이버와 다음의 주주예요 ^^)&lt;/SPAN&gt; &lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2008/11/27#23:38:11" rel=bookmark&gt;2008-11-27 23:38:11&lt;/A&gt;&lt;/SPAN&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://kr.finance.yahoo.com/news/view?aid=2008112715261127914"&gt;상장사 3분기 누적수출 224조, 25.5%↑&lt;/A&gt;: 환율의 영향이 크긴 컷었나 보군요. 예상되는 바였습니다. 좀 더 지나면 환율 영향은 사라지고 글로벌 경기 침체 영향으로 수출이 줄어들지 않을까 걱정되네요. &lt;SPAN class=me2_tags&gt;(인터넷오늘은 북마크 수출 경제)&lt;/SPAN&gt; &lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2008/11/27#23:43:17" rel=bookmark&gt;2008-11-27 23:43:17&lt;/A&gt;&lt;/SPAN&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://kr.finance.yahoo.com/news/view?aid=2008112717052232014&amp;amp;cate=1000"&gt;[내일의전략]산타랠리 기대해도 좋다&lt;/A&gt;: 단기 랠리에 그칠 것 같은데, 언론사들 항상 김치국부터 마신다 &lt;SPAN class=me2_tags&gt;(인터넷오늘은 북마크 경제 주식시장)&lt;/SPAN&gt; &lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2008/11/27#23:51:20" rel=bookmark&gt;2008-11-27 23:51:20&lt;/A&gt;&lt;/SPAN&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://media.daum.net/digital/view.html?cateid=1008&amp;amp;newsid=20081127083313615&amp;amp;p=etimesi"&gt;삼성서버엔 삼성SSD가 없다&lt;/A&gt;: 이 기사는 삼성전자 내부 사정을 모르는 기자가 작성한 듯. 작년에도 삼성전자 반도체 사업부가 자사 휴대폰 사업부보다 애플에 더 싼 값에 플래스 메모리를 공급했다는 걸 아시는지 모르시는지… &lt;SPAN class=me2_tags&gt;(인터넷오늘은 뉴스 삼성전자)&lt;/SPAN&gt; &lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2008/11/28#00:00:18" rel=bookmark&gt;2008-11-28 00:00:18&lt;/A&gt;&lt;/SPAN&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://media.daum.net/digital/others/view.html?cateid=100031&amp;amp;newsid=20081127111805296&amp;amp;p=inews24"&gt;'마이너리티 리포트' 컴퓨터 기술, 현실화된다&lt;/A&gt;: 이거 제품으로 나오면 꼭 사고 싶네요. 2~3년내 상품화 목표래요. &lt;SPAN class=me2_tags&gt;(인터넷오늘은 북마크 뉴스 HCI)&lt;/SPAN&gt; &lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2008/11/28#00:08:49" rel=bookmark&gt;2008-11-28 00:08:49&lt;/A&gt;&lt;/SPAN&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://www.zdnet.co.kr/news/internet/search/0,39031339,39175637,00.htm"&gt;한국판 '구글맵스' 흥행 성공할까?&lt;/A&gt;: 이런 소식을 이제서야 접하다니… 쩝~ 옛날에 구글이 한국 관련 데이터가 너무 부족하다고 1년전에 글을 썼었는데… 이제서야 데이터를 확보한건지 아니면 규제문제 때문이었는지… 아무튼 환영~ &lt;SPAN class=me2_tags&gt;(인터넷오늘은 북마크 뉴스 구글맵스 한국)&lt;/SPAN&gt; &lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2008/11/28#00:17:07" rel=bookmark&gt;2008-11-28 00:17:07&lt;/A&gt;&lt;/SPAN&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://www.zdnet.co.kr/news/enterprise/0,39031021,39175741,00.htm"&gt;DB도 토종 오픈소스 가능한가?…큐브리드의 대담한 도전&lt;/A&gt;: 다른 건 몰라도 License는 정말 잘 정했다. GPL과 BSD의 절묘한 조합이라고 해야겠네. 기술과 법을 다 잘 이해해야만 정할 수 있는 정책이다. &lt;SPAN class=me2_tags&gt;(인터넷오늘은 북마크 뉴스 오픈소스)&lt;/SPAN&gt; &lt;SPAN class=datetime&gt;&lt;A class=datetime title=퍼머링크 href="http://me2day.net/yesarang/2008/11/28#00:31:33" rel=bookmark&gt;2008-11-28 00:31:33&lt;/A&gt;&lt;/SPAN&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P style="PADDING-RIGHT: 25px; FONT-SIZE: 0.9em; BACKGROUND: url(http://me2day.net/images/me2day_icon.gif) no-repeat right top; TEXT-ALIGN: right"&gt;이 글은 &lt;A href="http://me2day.net/yesarang" target=_blank&gt;김윤수&lt;/A&gt;님의 &lt;A href="http://me2day.net/yesarang/2008/11/27#23:15:03"&gt;2008년 11월 27일&lt;/A&gt;에서 &lt;A href="http://me2day.net/yesarang/2008/11/28#00:31:33"&gt;2008년 11월 28일&lt;/A&gt;까지의 미투데이 내용입니다. &lt;/P&gt;&lt;/DIV&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2119027" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/TC1-cbpvH08" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>HCI</category>
			<category>경제</category>
			<category>구글맵스</category>
			<category>네이버와</category>
			<category>뉴스</category>
			<category>다음</category>
			<category>다음의</category>
			<category>맥</category>
			<category>북마크</category>
			<category>삼성전자</category>
			<category>수출</category>
			<category>스마트폰</category>
			<category>오픈소스</category>
			<category>와이브로</category>
			<category>인터넷오늘은</category>
			<category>전</category>
			<category>주식시장</category>
			<category>주주예요</category>
			<category>한국</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/351</guid>
			<comments>http://yesarang.tistory.com/351#entry351comment</comments>
			<pubDate>Fri, 28 Nov 2008 04:32:27 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/351</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 11월 27일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/Pj5JLwVX5Ho/350</link>
			<description>&lt;div class="me2day_daily_digest"&gt;
    &lt;ul&gt; 
      &lt;li&gt;
        &lt;a href='http://dev.naver.com/'&gt;Naver Developer Center&lt;/a&gt; 오픈했었군요. 이런 때 늦은 소식 접수라니… 쩝~
        &lt;span class="me2_tags"&gt;(네이버 개발자 센터 미투뉴스)&lt;/span&gt;
        &lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/27#02:00:41" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-27 02:00:41&lt;/a&gt;&lt;/span&gt;
        
      &lt;/li&gt;
      &lt;li&gt;
        &lt;a href='http://www.zeroboard.com/'&gt;제로보드 XE&lt;/a&gt;: 나도 내 홈페이지 함 만들어 볼까…
        &lt;span class="me2_tags"&gt;(인터넷생활 제로보드XE)&lt;/span&gt;
        &lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/27#02:32:26" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-27 02:32:26&lt;/a&gt;&lt;/span&gt;
        
      &lt;/li&gt;
      &lt;li&gt;
        우선 맥북에 제로보드랑 &lt;a href='http://www.apachefriends.org/en/xampp-macosx.html'&gt;맥용 APM 패키지&lt;/a&gt; 설치해서 써 본 후에 호스팅으로 옮겨 가야지
        &lt;span class="me2_tags"&gt;(인터넷생활 맥용APM)&lt;/span&gt;
        &lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/27#02:34:19" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-27 02:34:19&lt;/a&gt;&lt;/span&gt;
        
      &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;
      이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 
      &lt;a href="http://me2day.net/yesarang/2008/11/27#02:00:41"&gt;2008년 11월 27일&lt;/a&gt;의 
      미투데이 내용입니다.
    &lt;/p&gt;
  &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/Pj5JLwVX5Ho" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>개발자</category>
			<category>네이버</category>
			<category>맥용apm</category>
			<category>미투뉴스</category>
			<category>센터</category>
			<category>인터넷생활</category>
			<category>제로보드XE</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/350</guid>
			<comments>http://yesarang.tistory.com/350#entry350comment</comments>
			<pubDate>Thu, 27 Nov 2008 04:33:04 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/350</feedburner:origLink></item>
		<item>
			<title>다음 모바일 서비스 블로거 간담회에 다녀오다</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/D55Kp2lx_1c/349</link>
			<description>11월 26일 저녁 7시 &lt;a title="[http://info.daum.net/Daum/info/comingWay.do]로 이동합니다." target="_blank" href="http://info.daum.net/Daum/info/comingWay.do"&gt;다음 양재 사옥&lt;/a&gt; 3층에서 개최된 "&lt;a title="[http://daummobile.tistory.com/38]로 이동합니다." target="_blank" href="http://daummobile.tistory.com/38"&gt;다음 모바일 서비스 블로거 간담회&lt;/a&gt;"에 다녀왔습니다. 저로서는 아주 오랜만의 서울 나들이였습니다. 워낙 회사일도 바쁘고, 집안 가장으로서 해야할 일도 많고 해도 시간 내기가 여간 어렵지 않더군요. 그런 만큼 이번에는 머리도 식힐 겸 요즘 모바일 인터넷이 어떻게 돌아가는지도 알아볼 겸 해서 기대하는 마음으로 참석했습니다.&lt;br /&gt;
&lt;br /&gt;
행사장에 늦게 도착하지 않기 위해 급하게 나섰던지 너무 일찍 도착해서 주변에서 살짝 방황 좀 하다가 6:30분 쯤에 행사장에 들어갔습니다. &lt;a title="[http://me2day.net/jdpapa7]로 이동합니다." target="_blank" href="http://me2day.net/jdpapa7"&gt;지동아빠&lt;/a&gt;님(첨엔 몰랐는데 나중에 알았다는...)께서 식사는 6:50분에 제공되고, 행사는 식사후에 시작하게 된다고 하시더군요. 그래서 잠시 기다리는 동안 인터넷에 접속하려고 했으나... 헉! 무선랜이 안되더군요. ㅠ.ㅠ 순간 당황해서 패닉 상태에 빠질 뻔 했습니다. 혼미해지던 정신을 부여잡고 뭘해야하나 고민하던 중 &lt;a title="[http://me2day.net/goigoi]로 이동합니다." target="_blank" href="http://me2day.net/goigoi"&gt;고이고이&lt;/a&gt;님께서 아는체를 하셔서 겨우 정신 수습했습니다. 이 자리를 빌어서 고이고이님께 감사 ^^&lt;br /&gt;
&lt;br /&gt;
식사할 때는 같은 테이블에 &lt;a title="[http://me2day.net/sukhyun]로 이동합니다." target="_blank" href="http://me2day.net/sukhyun"&gt;빨판&lt;/a&gt;님, &lt;a title="[http://me2day.net/harmjang]로 이동합니다." target="_blank" href="http://me2day.net/harmjang"&gt;함장&lt;/a&gt;님, &lt;a title="[http://me2day.net/goigoi]로 이동합니다." target="_blank" href="http://me2day.net/goigoi"&gt;고이고이&lt;/a&gt;님, &lt;a title="[http://me2day.net/bigenius]로 이동합니다." target="_blank" href="http://me2day.net/bigenius"&gt;미소챨스&lt;/a&gt;님과 합석했습니다.&lt;br /&gt;
&lt;br /&gt;
행사 첫 오프닝은 oojoo라는 id로도 유명하신 김지현님(회사내 직책은 본부장이신가 보더군요)께서 하셨고, 기업이 블로그를 운영하는 것은 공개할 수 있는 정보와 공개해서는 안되는 정보 사이를 잘 조절해야 해서 어려움이 많지만 서비스를 혼자 만드는 거이 아니라 사용자와 같이 만든다고 생각하기 때문에 외부와 소통하기 위해 블로그를 운영하고 있고, 이번 간담회도 같은 맥락에서 1차로 준비한 서비스에 대한 의견을 듣고 싶어서 개최한 것이라고 배경 설명을 해 주셨습니다.&lt;br /&gt;
&lt;br /&gt;
그리고 이어서 지도 위에서 무궁 무진한 서비스가 펼쳐질 수 있다고 생각하고, 모바일 서비스의 킬러앱을 맵으로 보고 있다고 설명하시면서, 다음이 맵에 어떤 투자를 하고 있는지 실제 시연 장면을 통해 보여주셨습니다. 이 대목에서 기밀사항이라 사진 촬영은 금지! 저야 카메라가 없으니 말하지 않아도 찍을 수 없는 상황이었죠 ^^ 언뜻 보기에 맵 해상도가 상당히 고화질로 보이더군요. 스트릿뷰, 스카이뷰도 지원되고 요즘은 대부분 포털들이 고화질 맵 서비스를 제공하고 있어서 크게 달라 보이진 않았습니다. (여기서 아마 다음의 고민이 시작되겠지요? 어떻게 타사와 차별화 시킬 것인가?)&lt;br /&gt;
&lt;br /&gt;
이런 맵을 별도의 어플리케이션을 통해 모바일 폰에 올리려나 보더군요. 이런 맵 위에서 지명 검색, UCC 검색, 드라마 촬영지 검색, 경로 검색(버스, 지하철, 버스&amp;amp;지하철, 최적 경로, 최단 경로) 등도 가능하다고 합니다. 나중에 &lt;a title="[http://me2day.net/jdpapa7]로 이동합니다." target="_blank" href="http://me2day.net/jdpapa7"&gt;지동아빠&lt;/a&gt;님(모바일 애플리케이션 담당이시랍니다)께서 직접 테이블에 오셔서 시연도 해주셨습니다. 내년 쯤에서(내년 초라고 했는지 말이라고 했는지 기억이 나질 않네요 ㅠ.ㅠ) 모바일 맵 서비스가 가능하다고 하니 아직은 많이 기다려야 할 듯 합니다.&lt;br /&gt;
&lt;br /&gt;
이어서 풀브라우징 서비스와 모바일 애플리케이션에 대한 설명이 이어졌습니다. 풀브라우징 서비스 기획 담당하신 분은 금동우님이고 모바일 애플리케이션을 담당하신 분은 &lt;a title="[http://me2day.net/jdpapa7]로 이동합니다." target="_blank" href="http://me2day.net/jdpapa7"&gt;지동아빠&lt;/a&gt;님이시더군요. 전 두 분 다 초면이었습니다.&lt;br /&gt;
&lt;br /&gt;
풀브라우징 서비스는 현재로서는 아르고폰에 맞춰서 개발이 되었다고 하더군요. 아무리 모바일 폰이 UI가 좋다고 하더라도 단말 자체에 익숙해지는 것이 힘들다고 판단하여 "가독성", "편리한 스크롤", "가로/세로 대응", "PC화면 전환" 에 주안점을 두고 서비스를 개발했다고 합니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;가독성&lt;/span&gt;이야 화면이 많이 좁으니 폰트 크기를 적당히 맞춰져야 하므로 당연히 신경써야 하는 속성이었을 것 같구요(제 생각입니다), &lt;span style="font-weight: bold;"&gt;편리한 스크롤&lt;/span&gt;은 아직 국내에 출시된 스마트폰들이 아이폰만큼 부드러운 터치감과 스크롤을 제공해 주지 못하기 때문에 서비스 제공자 입장에서 그런 것들 보완할 수 있는 방안을 고민했다고 하더군요.&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;가로/세로 대응&lt;/span&gt;도 기존 왑 사용자의 경우 세로로 정보가 나열되는데 이미 익숙해져 있기 때문에 다른 모바일 서비스(모바일 파란을 예로 들었습니다)처럼 가로만 브라우징되도록 하는 것 좋지 않은 것이라 판단되어 가로/세로 모두 대응되도록 개발했다고 합니다.&lt;br /&gt;
마지막으로 &lt;span style="font-weight: bold;"&gt;"PC화면 전환"&lt;/span&gt;은 모바일 서비스에 최적화된 형태로 모든 정보를 변환하기는 상당히 시일이 소요될 것으로 예상되므로 더 상세한 정보를 얻고자 하는 사용자의 요구사항을 만족시키기 위해 "PC화면 전환"이라는 버튼을 매 페이지에 두었다고 합니다.&lt;br /&gt;
&lt;br /&gt;
현재 풀브라우징 외 모바일 애플리케이션으로 준비한 것은 TV팟과 지도 애플리케이션이라고 하더군요. TV팟 애플리케이션은 직접 사용도 해 봤는데 상당히 빠르게 응답하는 걸 봐서는 1차 버전임에도 상당히 최적화에 신경을 쓴 흔적이 보였습니다. 다만 시연시 사용했던 iPod Touch의 문제인지 아니면 동영상 자체 품질의 문제인지 화면에 잔상이 많이 남더군요. TV팟은 Hot, Best, Themes, Movies, Games 탭을 제공하고 있고, 아직 검색 기능은 제공하지 않습니다. &lt;a title="[http://www.futurewalker.kr/446]로 이동합니다." target="_blank" href="http://www.futurewalker.kr/446"&gt;퓨처워커&lt;/a&gt;님께서 왜 검색기능을 제공하지 않느냐는 질문을 주셨고 이에 대해 검색 기능을 제공하려면 모든 동영상을 TV팟 모바일 애플리케이션에 볼 수 있도록 인코딩을 해 놓아야 하는데, 아직 그렇게는 준비가 안되어 있다고 답변을 하시더군요. ROI때문에라도 모든 동영상은 모바일에 맞게 인코딩할 수는 없기 때문에 사용자들의 강력한 요구가 있을때에나 검색 기능을 추가할 수 있을 것이라며 검색 기능을 더 강력히 요청하라고 부추기시더군요. ^^&lt;br /&gt;
&lt;br /&gt;
저는 개인적으로 맵 정보를 바탕으로 풍부한 지역 정보 서비스가 제공되면 좋겠습니다. 그런 지역 정보 서비스가 &lt;a href="http://me2day.net" target="_blank" title="[http://me2day.net]로 이동합니다."&gt;미투데이&lt;/a&gt; 같은 마이크로 블로그 SNS와 연동이 되면 더욱 좋을 것 같구요. 정보가 맵에 집중되기도 하지만 각자의 마이크로 블로그에 분산되기도 하면서 그 안에서 관계를 맺는 것도 자연스러운 그런 서비스가 제공되면 좋겠습니다. 이런 서비스를 어떻게 구체적인 모습으로 만들지는 별 생각이 떠오르지 않지만요.&lt;br /&gt;
&lt;br /&gt;
이후 각 테이블에 아이팟 터치와 아르고폰을 나눠 주셔서 직접 조작하면서 풀브라우징 서비스와 TV팟 서비스를 사용해 볼 수 있었습니다. 풀브라우징 서비스 화면은 폰카로는 화질이 도저히 나오질 않아서 제 맥북의 내장 카메라로 어떻게 억지로 찍었는데 화질이 그닥 좋지 않습니다. OTL 그래도 글만 있으면 너무 심심할까봐 그림 첨부합니다. ^^&lt;br /&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;img src="http://cfs11.tistory.com/image/12/tistory/2008/11/26/00/53/492c1f66a8e0b" alt="" filemime="" filename="사진4.jpg" height="383" width="510"/&gt;&lt;/div&gt;&lt;br /&gt;
풀브라우징 초기화면은 &lt;a title="[http://daummobile.tistory.com/44]로 이동합니다." target="_blank" href="http://daummobile.tistory.com/44"&gt;이글&lt;/a&gt;을 보시면 더 정확히 알 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
저는 개인적으로 체험시간에 금동우님께 다음과 같은 질문을 했습니다.&lt;br /&gt;
&lt;br /&gt;
질문: 어떤 서비스가 모바일 풀브라우징 서비스가 되게 할 계획인지요?&lt;br /&gt;
답변: 현재 개발된 풀브라우징 서비스는 모두 소위 "노가다" 방식으로 개발한 것들이다. 이런 방법외에 구글과 같은 완전 자동 트랜스 코딩 방식, 오리가미 같은 준 트랜스코딩 방식이 있으나, 기술적인 한계 또는 비용 문제로 인해 보류했다. 그렇지만 소위 "노가다" 방식으로는 오래가지 못할 것이고 향후 보류했던 방식을 다시 시도해볼 수 있을 것이다.&lt;br /&gt;
다시질문: (질문의 의도를 파악하지 못하신 것 같아서) 그렇다고 하더라도 나중에 발표를 하실 때, 우리 서비스 중에 이런 이런 서비스들은 모바일 서비스가 제공된다라고 발표를 하실 거 아녜요? 어떤 서비스들을 계획하고 계신가요?&lt;br /&gt;
답변: 우선 메일, 검색, 뉴스는 1차로 개발되었고, 향후 증권, 티스토리, 부동산, 맵서비스도 준비중입니다.&lt;br /&gt;
질문: 모바일 폰에는 자신의 개인적인 정보도 많이 담기는데 모바일 폰 싱크 서비스는 계획하지 않고 계신가요?&lt;br /&gt;
답변: 모바일 폰 싱크 서비스도 준비 중이다.&lt;br /&gt;
&lt;br /&gt;
저는 솔직히 모바일 폰 싱크 서비스가 나오기를 바라는 사람이라서요. 제일 마지막 답변을 듣고 싶어서 저런 장황한 대화를 나눴었지요. ^^&lt;br /&gt;
&lt;br /&gt;
이외에 나중에 토론 시간에 BM에 대한 질문, 모바일 데이터 요금제 대책에 대한 질문, 모바일 사용자들의 사용 패턴 조사 여부에 대한 질문, 모바일 서비스에서 포털의 역할이 무엇이라고 생각하는지에 대한 질문 등 매우 까다로운 질문들이 오고 갔습니다. 이런 질문에 대한 답변은 참석하신 분들이 어딘가에 따로 포스팅하실 것을 기대하면서 저는 이만 줄여야 겠습니다. 벌써 새벽 1시가 넘어가네요.&lt;br /&gt;
&lt;br /&gt;
까다로운 질문으로 공격을 받으시던 김지현님께서 오히려 참석한 블로거들에게 질문을 하나 던지시더군요.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;"이렇게 모바일 서비스를 하는 게 어려운데 다음이 뛰어든게 답일까요?"&lt;/span&gt;&lt;br style="color: rgb(25, 61, 169); font-weight: bold;"&gt;&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;"저희들은 뛰어든게 답이라고 생각해서 이렇게 열심히 하고 있습니다. 모바일 서비스는 누구 하나의 노력으로 되지 않고 업계가 함께 노력해야 한다고 생각해서 타사와 협력해서 시장의 파이를 키우려고 노력중입니다. 앞으로 다음의 노력을 주목해 주십시오"&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
라는 말로 마무리를 지으시더군요.&lt;br /&gt;
&lt;br /&gt;
다음의 모바일 서비스 기대하고 있겠습니다. 쾌적하고, 즐겁고, 유용한 무선 인터넷을 만드시는데 노력해 주시기를 당부 드립니다. ^^&lt;br /&gt;
&lt;br /&gt;
(To 다음 모바일 TFT 관계자 분들께: 이 정도면 밥값은 한 건가요? 그리고 다음에는 무선랜 좀 되게 해주세요. ^^)&lt;br /&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2107335" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/D55Kp2lx_1c" height="1" width="1"/&gt;</description>
			<category>IT동향</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/349</guid>
			<comments>http://yesarang.tistory.com/349#entry349comment</comments>
			<pubDate>Wed, 26 Nov 2008 07:00:00 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/349</feedburner:origLink></item>
		<item>
			<title>C++이야기 스물여덟번째: map container에 STL algorithm적용하기</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/2vB-KjK8zOY/348</link>
			<description>If you are more familiar with English, then follow this link.&lt;br /&gt;
&lt;a href="http://yesarang.wordpress.com/2008/11/24/cpp-tips-28/" title="Permalink"&gt;C++ Tips 28th: Applying STL Algorithms to a Map&amp;nbsp;Container&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
여러분은 map container에 STL algorithm을 적용해 보신 적 있으신가요? map은 key=value pair를 저장해 두는 container라서 다른 container에 비해 STL algorithm을 적용하기가 쉽지 않더군요. map은 key 보다는 value에 관심이 있는 container라서 STL algorithm을 수행할 때도 key-value pair에 대해서 특정 작업을 수행하기 보다는 value에 대해서 어떤 작업을 수행하기를 원하는 경우가 많은데, STL algorithm 및 표준 함수 객체들이 map에 맞춰져 작성되어 있질 않아서 이걸 하기가 쉽지 않더군요. 그래서 별도의 Adaptor class를 정의하는 경우가 많습니다. 한 번 예를 들어 보겠습니다. 다음과 같은 클래스가 정의되어 있다고 가정해 보시죠.&lt;br /&gt;
&lt;br /&gt;
class Elem {&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Elem() : m_name(), m_val() {}&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Elem(const string&amp;amp; name, int val) : m_name(name), m_val(val) {}&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; const string&amp;amp; GetName() const&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return m_name;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; int GetValue() const&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return m_val;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; void SetValue(int val)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; m_val = val;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; void Print() const&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; GetName() &amp;lt;&amp;lt; "'s value ==&amp;gt; " &amp;lt;&amp;lt; GetValue() &amp;lt;&amp;lt; endl;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
private:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string m_name;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; int m_val;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
이 Elem 를 담는 map을 다음과 같이 정의해서 몇 개를 집어 넣어 보도록 하겠습니다.&lt;br /&gt;
&lt;br /&gt;
// 앞으로 설명에서 나오는 m container는 이걸 뜻합니다&lt;br /&gt;
map&amp;lt;string, Elem&amp;gt; m;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
m["1"] = Elem("1", 1);&lt;br /&gt;
m["2"] = Elem("2", 2);&lt;br /&gt;
m["3"] = Elem("3", 3);&lt;br /&gt;
m["4"] = Elem("4", 4);&lt;br /&gt;
m["5"] = Elem("5", 5);&lt;br /&gt;
&lt;br /&gt;
이 map에 담긴 모든 Elem 들의 값을 얻어내고 싶은 경우를 생각해 보겠습니다. 그렇다면 다음과 같이 for 루프를 작성할 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
// 먼저 값을 담을 vector를 정의합니다&lt;br /&gt;
vector&amp;lt;int&amp;gt; vi(m.size());&lt;br /&gt;
// 그리고 for 루프를 돌립니다&lt;br /&gt;
for (map&amp;lt;string, Elem&amp;gt;::iterator it = m.begin(); it != m.end(); ++it)&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp; vi.push_back(it-&amp;gt;second.GetValue());&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
소위 STL 좀 쓴다하는 여러분이 위와 같은 코드를 그냥 둘리 만무합니다. 어떻게 하면 저 for 루프를 STL 알고리즘으로 바꿀 수 없을까를 고민하시겠지요. 그리고 transform을 쓰면 되겠구나라고 맘을 먹습니다.&lt;br /&gt;
&lt;br /&gt;
// 먼저 algorithm header 파일을 포함해야죠&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;
#include &amp;lt;functional&amp;gt;&lt;br /&gt;
......&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;int&amp;gt; vi(m.size());&lt;br /&gt;
// m 에 들어가 있는 것은 포인터가 아니라 값이 들어가 있으므로 mem_fun이 아닌&lt;br /&gt;
// mem_fun_ref를 사용하여 멤버 함수 객체를 만듭니다&lt;br /&gt;
transform(m.begin(), m.end(), vi.begin(), mem_fun_ref(&amp;amp;Elem::GetValue));&lt;br /&gt;
&lt;br /&gt;
이 코드가 문제 없이 컴파일 돼서 실행될까요? 안타깝게도 그렇지 않습니다. transform이 기대하는 건 Elem 객체가 아닌 pair&amp;lt;string, Elem&amp;gt; 객체이기 때문에 컴파일 에러가 발생하지요. 여기서 잠깐 transform 알고리즘 속을 들여다 보면 왜 컴파일 에러가 발생하는지 좀 저 정확히 알 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
// 설명을 편하게 하기 위해 핵심 부분만 발췌했습니다.&lt;br /&gt;
template&amp;lt;typename _InputIterator, typename _OutputIterator,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typename _UnaryOperation&amp;gt;&lt;br /&gt;
_OutputIterator&lt;br /&gt;
transform(_InputIterator __first, _InputIterator __last,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _OutputIterator __result, _UnaryOperation __unary_op)&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp; for ( ; __first != __last; ++__first, ++__result)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;*__result = __unary_op(*__first);&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; return __result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
파랗게 표시한 부분을 보시면 first iterator를 dereference하고 있습니다. first iterator를 dereference하면 당연히 Elem 객체가 아닌 pair&amp;lt;string, Elem&amp;gt; 객체가 되는 것이지요.&lt;br /&gt;
&lt;br /&gt;
그렇다면 뭔가 Elem의 GetValue()를 호출해 줄 Adaptor가 필요하겠군요. 다음과 같이 Adaptor를 정의하면 될까요?&lt;br /&gt;
&lt;br /&gt;
struct ElemGetValueAdaptor {&lt;br /&gt;
&amp;nbsp; int operator()(const pair&amp;lt;string, Elem&amp;gt;&amp;amp; p) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return p.second.GetValue();&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
이런 클래스를 정의하고 나서 transform을 다음과 같이 호출하면 되겠습니다.&lt;br /&gt;
&lt;br /&gt;
transform(m.begin(), m.end(), vi.begin(), ElemGetValueAdaptor());&lt;br /&gt;
&lt;br /&gt;
뭐 여기까지는 할만합니다. 여기에 덧붙여 이번에는 m container에 있는 Elem 객체의 값을 출력해야 해서 Elem::Print()를 호출해야 하게 됐습니다. 그래서 Adaptor를 하나 더 정의합니다.&lt;br /&gt;
&lt;br /&gt;
struct ElemPrintAdaptor {&lt;br /&gt;
&amp;nbsp; void operator()(const pair&amp;lt;string, Elem&amp;gt;&amp;amp; p) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; p.second.Print();&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
그리고 나서 for_each를 다음과 같이 호출하면 되겠지요.&lt;br /&gt;
&lt;br /&gt;
for_each(m.begin(), m.end(), vi.begin(), ElemPrintAdaptor());&lt;br /&gt;
&lt;br /&gt;
이렇게 매번 멤버 함수를 호출하려고 할 때마다 Adaptor를 정의하면 얼마 있지 않아 코드에 온갖 Adaptor들이 난무하게 될 것입니다. 그리고, Adaptor들의 모양새라는 것도 거의 반복되는 코드이구요. 반복되는 코드를 보다보면 당연히 어떻게 하면 반복되는 코드를 없앨까를 생각하게 되죠. 그래서 이걸 템플릿으로 할 수 없을까를 생각하시게 될 것입니다.&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;typename R&amp;gt;&lt;br /&gt;
struct ElemAdaptor {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // GetValue()와 Print()가 모두 상수 멤버 함수라서 끝에 const를 붙임&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef R (Elem::*MemFunType)() const;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ElemAdaptor(MemFunType mf) : m_mf(mf) {}&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; R operator()(const pair&amp;lt;string, Elem&amp;gt;&amp;amp; p) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return (p.second.*m_mf)();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
private:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; MemFunType m_mf;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
그리고, transform과 for_each는 다음과 같이 호출하면 되겠지요.&lt;br /&gt;
&lt;br /&gt;
transform(m.begin(), m.end(), vi2.begin(), ElemAdaptor&amp;lt;int&amp;gt;(&amp;amp;Elem::GetValue));&lt;br /&gt;
 for_each(m.begin(), m.end(), ElemAdaptor&amp;lt;void&amp;gt;(&amp;amp;Elem::Print));&lt;br /&gt;
&lt;br /&gt;
이렇게 하면 GetValue()와 Print()는 커버할 수 있겠지만 SetValue(int)는 처리할 수 없습니다. Argument가 있기 때문입니다. 게다가 상수 멤버 함수도 아니구요. 이런 다양한 멤버함수를 처리할 수 있는 일반적인 멤버 함수 Adaptor를 만드는 건 보통 어려운 일이 아닙니다.&lt;br /&gt;
만약 m container가 Elem 객체의 container가 아니라 Elem* 의 container 거나 Elem&amp;amp;의 container이면 상황이 더 복잡해 질 것입니다. const나 volatile이 붙을 수도 있는 거구요. 이 모든 것들을 처리할 수 있는 일반적인 Adaptor를 만드는 건 무척이나 어려운 일이지요.&lt;br /&gt;
&lt;br /&gt;
이럴 때 써먹을 수 있는 게 boost::bind 와 placeholder입니다. boost::bind는 앞에서 제가 언급한 다양한 차이들을 모두 극복하고 하나의 함수로 모든 것을 수용할 수 있습니다. 위에서 제가 직접 만들었던 Adaptor를 쓰지 않고 bind를 쓰는 방식으로 바꾼다면 다음과 같이 작성하시면 됩니다.&lt;br /&gt;
&lt;br /&gt;
// boost::bind&lt;br /&gt;
#include &amp;lt;boost/bind.hpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
using namespace boost;&lt;br /&gt;
......&lt;br /&gt;
transform(&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; m.begin(), m.end(), vi2.begin(), &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;bind(&amp;amp;Elem::GetValue, bind(&amp;amp;map&amp;lt;string, Elem&amp;gt;::value_type::second, _1))&lt;/span&gt;&lt;br /&gt;
);&lt;br /&gt;
for_each(&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; m.begin(), m.end(),&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;bind(&amp;amp;Elem::Print, bind(&amp;amp;map&amp;lt;string, Elem&amp;gt;::value_type::second, _1))&lt;/span&gt;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
inner bind() 즉 bind(&amp;amp;map&amp;lt;string, Elem&amp;gt;::value_type::second, _1) 이렇게 된 부분을 먼저 설명드리면, _1은 placeholder라고 하여 _1이라고 표시된 부분에 인자를 받을 수 있는 함수자(functor)를 만들어주게 됩니다. transform과 for_each는 각각 pair&amp;lt;string, Elem&amp;gt;를 입력인자로 하여 해당 알고리즘의 마지막 인자로 주어진 함수자를 호출할 것이므로 _1 placeholder를 써서 인자를 받을 수 있도록 한 것입니다. 그리고 inner bind의 첫번째 인자로 멤버 변수에 대한 포인터를 주게 되면, 두번째 인자로 주어진 객체(이 경우 _1)에 대해 멤버로 참조할 수 있도록 만들어 줍니다. &amp;amp;map&amp;lt;string, Elem&amp;gt;::value_type::second 라고 한 부분은 당연히 map 에서 Elem 객체를 참조할 수 있도록 하기 위한 것입니다. 이 설명을 종합하자면 inner bind는 pair&amp;lt;string, Elem&amp;gt; 객체에서 Elem 객체를 선택하는 부분이라고 생각하시면 되겠습니다. 즉, ElemAdaptor::operator(p) 의 구현에서 p.second 에 해당하는 부분이라고 생각하시면 되겠습니다.&lt;br /&gt;
&lt;br /&gt;
이걸 바탕으로 outer bind를 좀 더 쉽게 표현해 보자면 bind(Elem_mem_func_ptr, Elem_obj), 이런 의미가 되겠습니다. bind는 첫번째 인자가 멤버 포인터(멤버 변수에 대한 포인터이건 멤버 함수에 대한 포인터이건 상관 없이)이면 두번째 인자를 객체(또는 객체 참조자 또는 객체 포인터)로 해석하고 해당 객체에 대해 멤버 변수나 멤버 함수를 접근 또는 호출해주는 함수자를 만들어 줍니다. 그래서 결국은 (Elem_obj.*Elem_mem_func_ptr)() 또는 (Elem_obj-&amp;gt;*Elem_mem_func_ptr)() 의 효과가 있게 됩니다.&lt;br /&gt;
&lt;br /&gt;
bind는 꼭 인자가 없는 멤버 함수에만 쓸 수 있는 건 아닙니다. 실은 인자를 9개까지 지원해 줍니다. 예를 들어, m container를 각 Elem 객체에 대해 Elem::SetValue(10) 를 호출하고 싶다면 다음과 같이 하시면 됩니다.&lt;br /&gt;
&lt;br /&gt;
for_each(&lt;br /&gt;
&amp;nbsp; m.begin(), m.end(),&lt;br /&gt;
&amp;nbsp; bind(&amp;amp;Elem::SetValue, bind(&amp;amp;map&amp;lt;string, Elem&amp;gt;::value_type::second, _1), 10)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
bind의 세번째 인자로 SetValue()의 인자값을 bind 하면 되는 것이지요.&lt;br /&gt;
&lt;br /&gt;
정리하자면 map container에 STL algorithm을 적용하고 싶을 때는 boost::bind와 placeholder를 다음과 같은 패턴으로 사용하시면 되겠습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;#include &amp;lt;boost/bind.hpp&amp;gt;&lt;/span&gt;&lt;br style="color: rgb(25, 61, 169); font-weight: bold;"&gt;&lt;br style="color: rgb(25, 61, 169); font-weight: bold;"&gt;&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;using namespace boost;&lt;/span&gt;&lt;br style="color: rgb(25, 61, 169); font-weight: bold;"&gt;&lt;br style="color: rgb(25, 61, 169); font-weight: bold;"&gt;&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;bind(&amp;amp;ClassName::mem_func_name, bind(&amp;amp;map&amp;lt;keytype,&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ClassName&amp;gt;::value_type::second, _1), arg1, arg2, ..., arg9)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
그럼 여러분의 C++ 프로그래밍에 조금이라도 도움이 되길 바라면서 이만 줄여야겠네요.&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2096524" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/2vB-KjK8zOY" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/348</guid>
			<comments>http://yesarang.tistory.com/348#entry348comment</comments>
			<pubDate>Mon, 24 Nov 2008 07:00:00 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/348</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 11월 21일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/fZcND4-9v6g/347</link>
			<description>&lt;div class="me2day_daily_digest"&gt;
    &lt;ul&gt; 
      &lt;li&gt;
        &lt;a href='http://msdn.microsoft.com/ko-kr/magazine/cc164244.aspx'&gt;F# Primer&lt;/a&gt;: F# 소개 기사네요. 이제는 함수형 언어에도 관심을 많이 가져 봐야 겠어요
        &lt;span class="me2_tags"&gt;(SW개발 프로그래밍언어 fsharp F#)&lt;/span&gt;
        &lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/21#22:57:30" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-21 22:57:30&lt;/a&gt;&lt;/span&gt;
        
      &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;
      이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 
      &lt;a href="http://me2day.net/yesarang/2008/11/21#22:57:30"&gt;2008년 11월 21일&lt;/a&gt;의 
      미투데이 내용입니다.
    &lt;/p&gt;
  &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/fZcND4-9v6g" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>f</category>
			<category>fsharp</category>
			<category>sw개발</category>
			<category>프로그래밍언어</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/347</guid>
			<comments>http://yesarang.tistory.com/347#entry347comment</comments>
			<pubDate>Sat, 22 Nov 2008 04:33:01 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/347</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 11월 19일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/7h3zksPmuIM/346</link>
			<description>&lt;div class="me2day_daily_digest"&gt;
    &lt;ul&gt; 
      &lt;li&gt;
        간단팁: subversion에서 변경된 소스 목록 알아내기 —&amp;gt; svn status | grep '^M' | cut -b 8-
        &lt;span class="me2_tags"&gt;(간단팁)&lt;/span&gt;
        &lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/18#21:40:05" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-18 21:40:05&lt;/a&gt;&lt;/span&gt;
        
      &lt;/li&gt;
      &lt;li&gt;
        간단팁: 그리고, 변경된 소스 각각에 대해 diff 알아내기 —&amp;gt; foreach f in `svn status | grep '^M' | cut -b 8-`; do; svn diff $f; done;
        &lt;span class="me2_tags"&gt;(간단팁 여러분도 알고 있는 팁 있으면 공유해요)&lt;/span&gt;
        &lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/18#21:42:14" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-18 21:42:14&lt;/a&gt;&lt;/span&gt;
        
      &lt;/li&gt;
      &lt;li&gt;
        &lt;a href='http://yesarang.wordpress.com/2008/11/19/ive-just-started-blogging-about-software-development/'&gt;I've just started blogging in English&lt;/a&gt; about software development
        &lt;span class="me2_tags"&gt;(blog blogging)&lt;/span&gt;
        &lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/19#00:49:59" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-19 00:49:59&lt;/a&gt;&lt;/span&gt;
        
      &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;
      이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 
      &lt;a href="http://me2day.net/yesarang/2008/11/18#21:40:05"&gt;2008년 11월 18일&lt;/a&gt;에서 
      &lt;a href="http://me2day.net/yesarang/2008/11/19#00:49:59"&gt;2008년 11월 19일&lt;/a&gt;까지의 
      미투데이 내용입니다.
    &lt;/p&gt;
  &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/7h3zksPmuIM" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>blog</category>
			<category>blogging</category>
			<category>간단팁</category>
			<category>공유해요</category>
			<category>알고</category>
			<category>여러분도</category>
			<category>있는</category>
			<category>있으면</category>
			<category>팁</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/346</guid>
			<comments>http://yesarang.tistory.com/346#entry346comment</comments>
			<pubDate>Wed, 19 Nov 2008 04:34:26 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/346</feedburner:origLink></item>
		<item>
			<title>Timer class 검토 좀 해주세요~</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/_Wjsy_CzAbw/345</link>
			<description>&lt;br /&gt;
Timer class 를 아래와 같이 구현하려고 하는데... 괜찮은 설계일까요?&lt;br /&gt;
&lt;br /&gt;
struct Timer&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef boost::function&amp;lt;void ()&amp;gt; CallbackObjectType;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Timer(int period, CallbackObjectType cbo) :&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; m_period(period), m_cbo(cbo)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {}&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; int m_period;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; CallbackObjectType m_cbo;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
inline Timer &lt;br /&gt;
MakeTimer(int period, void (*func)())&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Timer::CallbackObjectType cbo = func;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return Timer(period, cbo);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;typename Callee&amp;gt;&lt;br /&gt;
struct CallbackMemFunc0 {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (Callee::*Type)();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;typename Callee&amp;gt;&lt;br /&gt;
inline Timer&lt;br /&gt;
MakeTimer(int period, Callee* callee, const typename CallbackMemFunc0&amp;lt;Callee&amp;gt;::Type&amp;amp; memFunc)&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return Timer(period, boost::bind(memFunc, callee));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;typename ArgType&amp;gt;&lt;br /&gt;
struct CallbackFunc1 {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (*Type)(ArgType);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;typename ArgType&amp;gt;&lt;br /&gt;
inline Timer&lt;br /&gt;
MakeTimer(int period, const typename CallbackFunc1&amp;lt;ArgType&amp;gt;::Type&amp;amp; func, ArgType arg)&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return Timer(period, boost::bind(func, arg));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;typename Callee, typename ArgType&amp;gt;&lt;br /&gt;
struct CallbackMemFunc1 {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (Callee::*Type)(ArgType);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;typename Callee, typename ArgType&amp;gt;&lt;br /&gt;
inline Timer&lt;br /&gt;
MakeTimer(int period, Callee* callee, &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; const typename CallbackMemFunc1&amp;lt;Callee, ArgType&amp;gt;::Type&amp;amp; memFunc, &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; ArgType arg)&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return Timer(period, boost::bind(memFunc, callee, arg));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
굳이 Timer class는 encapsulation 시킬 필요가 없다고 생각해서 그냥 struct로 선언해 버렸구요. MakeTimer를 여러개 만들어 놓았는데... 아무리 봐도 맘에 안드네요. 결국은 계속해서 반복되는 코드 패턴이라서... 게다가 컴파일러가 template &amp;lt;typename Callee&amp;gt; MakeTimer(...) 와&amp;nbsp; template &amp;lt;typename ArgType&amp;gt; MakeTimer(...)를 잘 구분못해서 사용자가 직접 template 인자를 알려줘야 해서 불편하기도 하고...&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Timer t(100, bind(&amp;amp;Base::print, new Base()));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Timer t1 = MakeTimer(100, new Base(), &amp;amp;Base::print);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; t1.m_cbo();&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Timer t2 = &lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;MakeTimer&amp;lt;const string&amp;gt;&lt;/span&gt;(100, sayHelloTo, string("YoonSoo Kim"));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; t2.m_cbo();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Timer t3 = MakeTimer(100, new Hello(), &amp;amp;Hello::sayHelloTo, string("YoonSoo Kim"));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; t3.m_cbo();&lt;br /&gt;
&lt;br /&gt;
이렇게 반복되는 코드 없이 깔끔하게 설계할 수 있는 방법은 없을까요????&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2074202" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/_Wjsy_CzAbw" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<category>c++</category>
			<category>sw개발</category>
			<category>timer</category>
			<category>프로그래밍</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/345</guid>
			<comments>http://yesarang.tistory.com/345#entry345comment</comments>
			<pubDate>Tue, 18 Nov 2008 23:20:13 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/345</feedburner:origLink></item>
		<item>
			<title>C++이야기 스물일곱번째: C++에 돌연변이가 있었나?</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/kPWJSOcRu2o/344</link>
			<description>&lt;a href="http://yesarang.tistory.com/343" target="_blank"&gt;2008/11/15 - [S/W개발/C++ 이야기] - C++이야기 스물여섯번째: constness를 활용한 멤버 함수 overloading&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
이전 글 말미에 const 멤버 함수와 밀접한 관련이 있는 mutable에 소개해 드린다고 했는데... 왜 제목을 "C++에 돌연변이가 있었나?"라고 지었을까요?&lt;br /&gt;
&lt;br /&gt;
X-Men 1,2 보신 분들이나 요즘 유행하는 미드 중 Heroes를 즐겨 보시는 분들은 잘 아시겠지만 돌연 변이를 영어로 &lt;a title="[http://engdic.daum.net/dicen/small_search.do?endic_kind=all&amp;amp;m=all&amp;amp;q=mutant]로 이동합니다." target="_blank" href="http://engdic.daum.net/dicen/small_search.do?endic_kind=all&amp;amp;m=all&amp;amp;q=mutant"&gt;mutant&lt;/a&gt;라고 합니다. 왠지 mutable과 mutant가 서로 형제지간일 것 같지 않으세요? 그렇습니다. &lt;a title="[http://engdic.daum.net/dicen/small_search.do?endic_kind=all&amp;amp;m=all&amp;amp;q=mutable]로 이동합니다." target="_blank" href="http://engdic.daum.net/dicen/small_search.do?endic_kind=all&amp;amp;m=all&amp;amp;q=mutable"&gt;mutable&lt;/a&gt;의 사전적 의미는 변할 수 있는이라는 뜻으로 &lt;a title="[http://engdic.daum.net/dicen/small_search.do?endic_kind=all&amp;amp;m=all&amp;amp;q=constant]로 이동합니다." target="_blank" href="http://engdic.daum.net/dicen/small_search.do?endic_kind=all&amp;amp;m=all&amp;amp;q=constant"&gt;constant&lt;/a&gt;와는 반대의 뜻을 가지고 있습니다.&lt;br /&gt;
&lt;br /&gt;
이 대목에서 mutable과 const의 복잡 미묘한 관계를 읽을 수 있는데요... 겉으로 보기에 서로 티격태격 싸우는 사이일 것 같지만 실제로는 서로 힘을 합쳐 멋진 코드를 만들어 낸답니다.&lt;br /&gt;
&lt;br /&gt;
지난 번에 이어 class Foo를 예제로 들어 얘기 보따리를 풀어 보도록 하겠습니다.&lt;br /&gt;
&lt;br /&gt;
지난 글에서 class Foo 에 다음과 같이 toString()과 toString() const를 정의했었습니다.&lt;br /&gt;
(실제 코드에서는 toString()과 같은 멤버 함수가 string&amp;amp;를 리턴할 리는 없을 것입니다. 그냥 예제로 든 것이니 toString()과 같은 멤버 함수를 이런식으로 구현하는 일은 피하시기 바랍니다)&lt;br /&gt;
&lt;br /&gt;
class Foo&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string&amp;amp; toString();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string toString() const;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
이렇게 정의해 놓고 한참을 잘 사용하고 있었는데, 갈수록 프로그램이 방대해지다 보니 어딘가 모르게 프로그램이 느려진다는 고객의 claim이 있어 성능 프로파일러를 돌려 봤더니 string toString() const이 무척 자주 호출된다는 걸 발견하게 됐습니다. 그래서 string toString() const의 성능을 개선하기로 마음을 먹었습니다. 한참 코드를 분석해 본 결과, toString()으로 리턴하는 값은 별로 자주 바뀌지 않기 때문에 string toString() const가 호출될 때마다 매번 값을 계산해서 리턴할 필요가 없다고 결론을 내리게 됐습니다. 그래서 이제는 내부적으로 계산된 값을 유지하고 그 값을 바로 리턴하는 식으로 구현을 바꾸려고 합니다. 물론, 내부적으로 유지되는 미리 계산된 값은 계산이 필요한 경우에 바로 update 하도록 하구요. 그래서 먼저, m_str이라는 멤버 변수와 m_needCompute 멤버 변수를 추가하기로 했습니다.&lt;br /&gt;
&lt;br /&gt;
class Foo&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string&amp;amp; toString();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string toString() const;&lt;br /&gt;
&lt;br /&gt;
private:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string m_str;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; bool m_needCompute;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
눈누난나하면서 다음과 같이 string Foo::toString() const를 구현하고 컴파일합니다.&lt;br /&gt;
&lt;br /&gt;
string&lt;br /&gt;
Foo::toString() const&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // 새로 계산이 필요한 경우에만 새로 계산한 후... 계산된 값을 m_str에 assign 합니다.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_needCompute)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_str = computeString();&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return m_str;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
아니 그런데 이게 왠 일입니까? 컴파일해 봤더니 바로 에러가 뜨는 것 아닙니까?&lt;br /&gt;
&lt;br /&gt;
error: passing 'const std::string' as 'this' argument of 'std::basic_string&amp;lt;_CharT, _Traits, _Alloc&amp;gt;&amp;amp; std::basic_string&amp;lt;_CharT, _Traits, _Alloc&amp;gt;::operator=(const _CharT*) [with _CharT = char, _Traits = std::char_traits&amp;lt;char&amp;gt;, _Alloc = std::allocator&amp;lt;char&amp;gt;]' discards qualifiers&lt;br /&gt;
&lt;br /&gt;
음... 이눔의 컴파일러 또 난리네... 투덜투덜!&lt;br /&gt;
&lt;br /&gt;
자세히 들여다 봤더니 m_str = computeString() 이 부분이 말썽이네요. const 멤버 함수에 넘겨지는 this 는 상수 객체이고 당연히 멤버들도 모두 상수 객체인데, m_str 값을 변경하고 있다고 컴파일러가 투덜거렸던 것입니다. 이유 있는 반항이네요.&lt;br /&gt;
&lt;br /&gt;
이럴 때 잘쓰는 비법 컴파일러 속이기 신공을 발휘합니다. 니가 뛰면 나는 난다. 크하하하 쾌재를 부르며 코드를 다음과 같이 고칩니다.&lt;br /&gt;
&lt;br /&gt;
string&lt;br /&gt;
Foo::toString() const&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // 새로 계산이 필요한 경우에만 새로 계산한 후... 계산된 값을 m_str에 assign 합니다.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_needCompute)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_cast&amp;lt;Foo*&amp;gt;(this)-&amp;gt;m_str = computeString();&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return m_str;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
에러없이 잘 컴파일 되는군요. 그럼 그렇지 지가 무슨 용가리 똥배라고 나의 컴파일러 속이기 신공을 피할 수 있겠어. 이제 mentor 선배에게 코드 리뷰 받아야지. 선배에게 새로 작성한 코드를 보여 줬더니 오른쪽 눈썹이 파르르 떨리는 게 표정이 좋질 않습니다.&lt;br /&gt;
&lt;br /&gt;
선배: "string Foo::toString() const 구현에서 꼭 const_cast를 써야 하나요? XXX씨는 너무 컴파일러 속이기를 잘 쓰는 것 같애~ 컴파일러 속이기 신공은 정말 정말 어쩔 수 없을 때만 쓰는 거예요. 컴파일러의 type system을 우회하는 것이기 때문에 언제 버그가 끼어들지 모르는 방식이잖아요"&lt;br /&gt;
&lt;br /&gt;
XXX: (에이~ 또 괜한 생트집 잡는다고 생각하며)"거기에서 m_str 멤버 변수를 수정해야 하는데 어떡해요. 그렇다고 const를 뗄 수는 없구요."&lt;br /&gt;
&lt;br /&gt;
선배: "그럼 m_str 앞에 mutable을 붙여 보세요. 그럴 때 쓰라고 있는 게 mutable인데?"&lt;br /&gt;
&lt;br /&gt;
XXX: (O.O 엥? mutable이 뭐지? 이 선배가 요즘 Heroes를 보더니 mutant랑 뭐가 헤깔리나?)"mutable이요? mutable이 뭔데요? 그런게 있어요?"&lt;br /&gt;
&lt;br /&gt;
선배: "&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;mutable은 상수 멤버 함수에서도 수정이 필요한 멤버 변수에 붙이는 거예요. 상수 멤버 함수 안에서 그 멤버 변수를 수정하더라도 컴파일에러가 나지 않죠&lt;/span&gt;"&lt;br /&gt;
&lt;br /&gt;
XXX: (설마 그럴리가? 나도 C++이라면 좀 한다하는 놈인데 그런 듣보잡이 있을리가)"정말 그런게 있어요?"&lt;br /&gt;
&lt;br /&gt;
선배: "그런 게 있죠. 언제적부터 있던 건데... 얼른 수정하세요. 그것만 수정하면 다른 곳은 다 잘 작성했네요"&lt;br /&gt;
&lt;br /&gt;
약간 자존심은 상했지만 코드를 다음과 같이 수정한 후 컴파일해 보았습니다.&lt;br /&gt;
&lt;br /&gt;
class Foo&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string&amp;amp; toString();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string toString() const;&lt;br /&gt;
&lt;br /&gt;
private:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;mutable&lt;/span&gt; string m_str;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; bool m_needCompute;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
string&lt;br /&gt;
Foo::toString() const&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // 새로 계산이 필요한 경우에만 새로 계산한 후... 계산된 값을 m_str에 assign 합니다.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_needCompute)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;m_str = computeString();&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return m_str;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
오~~~ 아무런 에러 없이 컴파일이 되네~~~~? 우왕ㅋ굳ㅋ 선배가 괜히 선배가 아니었네. 이야~ 덕분에 돌연변이 신공도 하나 배웠네.&lt;br /&gt;
&lt;br /&gt;
어때요? 재미 있으셨나요? 약간은 이야기 식으로 설명해 보았는데 잘 이해가 되셨는지 모르겠습니다. 요약하자면&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;"const 멤버 함수 안에서도 수정이 필요한 멤버 변수가 있다면 mutable을 사용하자"&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
입니다. mutable과&amp;nbsp; const 의 하모니로 만들어낸 멋진 코드였습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2063449" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/kPWJSOcRu2o" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<category>C++이야기</category>
			<category>const</category>
			<category>mutable</category>
			<category>Programming</category>
			<category>sw개발</category>
			<category>팁</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/344</guid>
			<comments>http://yesarang.tistory.com/344#entry344comment</comments>
			<pubDate>Sun, 16 Nov 2008 16:30:09 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/344</feedburner:origLink></item>
		<item>
			<title>C++이야기 스물여섯번째: constness를 활용한 멤버 함수 overloading</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/RHfA30-2oAs/343</link>
			<description>C++로 작성된 클래스 API에서 멤버 함수 끝에 const가 붙은 걸 보신적 있으신가요? 상수객체에 대고 const가 붙어 있지 않은 멤버 함수를 호출할 수 없는 것도 다 아시리라 생각합니다.&lt;br /&gt;
&lt;br /&gt;
/// @file &amp;nbsp; const.cpp&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
class Foo&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; void modify()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; __PRETTY_FUNCTION__ &amp;lt;&amp;lt; " called" &amp;lt;&amp;lt; endl;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; void dontModify() const&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; __PRETTY_FUNCTION__ &amp;lt;&amp;lt; " called" &amp;lt;&amp;lt; endl;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int&lt;br /&gt;
main()&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; const Foo foo;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; foo.modify();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
이걸 g++로 컴파일하면 다음과 같은 에러가 발생합니다.&lt;br /&gt;
&lt;br /&gt;
error: passing 'const Foo' as 'this' argument of 'void Foo::modify()' discards qualifiers&lt;br /&gt;
&lt;br /&gt;
해석하자면 const Foo를 Foo::modify()의 인자로 넣게 되면 constness qualifier가 없어져 버린다는 뜻이죠. Foo::modify()는 변경가능한 this를 필요로 하는데(함수 Signature 마지막에 const가 붙어 있질 않습니다), const Foo를 변경가능한 this로 바꿔서 넣어주면 안된다는 얘기입니다. modify()를 호출하지 않고, dontModify()를 호출하면 컴파일도 잘되고 실행도 잘됩니다.&lt;br /&gt;
&lt;br /&gt;
int&lt;br /&gt;
main()&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; const Foo foo;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; foo.dontModify();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$ ./const&lt;br /&gt;
void Foo::dontModify() const called&lt;br /&gt;
&lt;br /&gt;
이런 const 멤버 함수 특성을 이용하면 클래스 API의 사용자가 실수로 상수 객체를 변경하는 일을 막을 수 있게 됩니다. 그래서 C++ 좀 쓸 줄 안다하는 사람은 const를 애용해서 사용합니다. 저도 const를 애용하고 있구요. (흠... 이건 뭥미? 지 자랑? 쿨럭 쿨럭)&lt;br /&gt;
&lt;br /&gt;
C++를 좀 쓸 줄 안다고 자신하던 여러분에게 새로운 도전이 왔습니다. const 객체인 경우와 그렇지 않은 객체에 대해 동일한 기능을 하는 멤버 함수를 제공해야 하고, 그 멤버 함수가 워낙 자주 사용되기 때문에 성능도 좋게 해야할 필요가 있다는 것입니다. 예를 들어, Foo 클래스의 멤버 함수로 toString()이 있는데 이게 그런 case라고 생각해 보겠습니다. 여러분이라면 어떻게 이 도전에 응전을 하시겠습니까?&lt;br /&gt;
&lt;br /&gt;
이렇게 하면 어떨까요?&lt;br /&gt;
&lt;br /&gt;
class Foo&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string&amp;amp; toString()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {}&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string toStringConst() const&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
즉, 비상수 객체를 위한 toString() 과 상수객체를 위한 toStringConst()를 따로 두는 것이지요. 이것도 괜찮은 방법인 것 같습니다. 그런데, 이렇게 할 경우 사용자가 자신이 상수 객체를 다룰 때와 비상수 객체를 다룰 때 어떤 멤버 함수를 쓸 수 있는지를 따로 기억하고 있어야 하는 부담이 있습니다. 물론, Foo야 별 문제가 없지만 멤버 함수가 많은 클래스라면 어떻게 될까요? 항상 시스템이 간단할 때는 별로 문제가 되지 않지요. 복잡해질때 문제가 되니까요.&lt;br /&gt;
&lt;br /&gt;
바로 이럴 때 활용할 수 있는 방법이 constness를 활용한 멤버 함수 overloading입니다. 다음과 같이 toString()을 정의하면 원하는 목적을 달성할 수 있을 것 같습니다.&lt;br /&gt;
&lt;br /&gt;
class Foo&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
&lt;span style="font-weight: bold; color: rgb(25, 61, 169);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; string&amp;amp; toString()&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; __PRETTY_FUNCTION__ &amp;lt;&amp;lt; " called" &amp;lt;&amp;lt; endl;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold; color: rgb(25, 61, 169);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; string toString() const&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; __PRETTY_FUNCTION__ &amp;lt;&amp;lt; " called" &amp;lt;&amp;lt; endl;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int&lt;br /&gt;
main()&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Foo foo1;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; const Foo foo2;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Foo&amp;amp; rfoo1 = foo1;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; const Foo&amp;amp; rfoo2 = foo2;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; foo1.toString();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; rfoo1.toString();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; foo2.toString();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; rfoo2.toString();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
이걸 컴파일해서 실행해 보면 다음과 같은 결과가 출력됩니다.&lt;br /&gt;
&lt;br /&gt;
$ ./const&lt;br /&gt;
std::string&amp;amp; Foo::toString() called&lt;br /&gt;
std::string&amp;amp; Foo::toString() called&lt;br /&gt;
std::string Foo::toString() const called&lt;br /&gt;
std::string Foo::toString() const called&lt;br /&gt;
&lt;br /&gt;
즉 객체가 비상수 객체냐 상수 객체냐에 따라 적절한 멤버 함수가 호출되는 것이지요. 게다가 const 가 붙지 않은 경우에는 string&amp;amp;를 리턴해서 리턴값이 복사되지 않도록 하면서 성능도 최적화했고, 클래스 API 사용자도 toString()이라는 멤버 함수만 기억하면 되니 한결 수월해지겠지요. 이 방법은 함수의 Signature에 const가 포함되는 사실을 이용한 것입니다.&lt;br /&gt;
&lt;br /&gt;
여러분이 설계하는 클래스 API에 const를 활용한 overload 기법을 적용한다면 제가 장담하건데 그걸 보는 사람들이 "C++ 좀 많이 쓸 줄 아네"라고 할 것이니 잘 활용해 보시기 바랍니다. ^^&lt;br /&gt;
&lt;br /&gt;
다음글에서는 const 멤버 함수와 밀접한 관련이 있는 mutable 키워드에 대해 알아보도록 하겠습니다.&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2058854" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/RHfA30-2oAs" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<category>c++</category>
			<category>C++이야기</category>
			<category>const</category>
			<category>Overloading</category>
			<category>Programming</category>
			<category>sw개발</category>
			<category>상수멤버함수</category>
			<category>팁</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/343</guid>
			<comments>http://yesarang.tistory.com/343#entry343comment</comments>
			<pubDate>Sat, 15 Nov 2008 17:15:24 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/343</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 11월 15일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/wJvGiWu0z9s/342</link>
			<description>&lt;div class="me2day_daily_digest"&gt;
    &lt;ul&gt; 
      &lt;li&gt;
        &lt;a href='http://yesarang.tistory.com/341'&gt;Inter-thread communication library in C++ v0.1&lt;/a&gt;
        &lt;span class="me2_tags"&gt;(SW개발 ITC inter thread communication C++ programming cpp ITCSignal v0.1)&lt;/span&gt;
        &lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/15#01:27:14" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-15 01:27:14&lt;/a&gt;&lt;/span&gt;
        
      &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;
      이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 
      &lt;a href="http://me2day.net/yesarang/2008/11/15#01:27:14"&gt;2008년 11월 15일&lt;/a&gt;의 
      미투데이 내용입니다.
    &lt;/p&gt;
  &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/wJvGiWu0z9s" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>1</category>
			<category>c</category>
			<category>communication</category>
			<category>cpp</category>
			<category>Inter</category>
			<category>itc</category>
			<category>itcsignal</category>
			<category>Programming</category>
			<category>sw개발</category>
			<category>thread</category>
			<category>v0</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/342</guid>
			<comments>http://yesarang.tistory.com/342#entry342comment</comments>
			<pubDate>Sat, 15 Nov 2008 04:34:27 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/342</feedburner:origLink></item>
		<item>
			<title>Inter-thread communication library in C++ v0.1</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/E1XHpHwiZj8/341</link>
			<description>Inter-thread communication library에 signal 기능까지 구현해서 이제 어느 정도 모양새를 갖춘 것 같습니다. 그래서 버전을 한 번 붙여 보았지요. ^^ 지난 번과 비교해서 signal 구현이 가장 크게 바뀐 부분이니 그 부분을 중심으로 말씀드리겠습니다.&lt;br /&gt;
&lt;br /&gt;
signal 클래스의 이름은 ITCSignal0, ITCSignal1, ITCSignal2, ITCSignal3 입니다. 각각 인자가 0개, 1개, 2개, 3개가 있는 slot을 연결 할 때 사용합니다. Call Trait를 분해하고 합성하는 방법에 익숙하면 boost::signal 이나 boost::function 처럼 ITCSignal 클래스 하나만 정의하고, 함수 Signature 전체를 type으로 받아들이는 식으로 할 수 있을텐데 아직 내공이 부족하여 거기까진 못하겠더군요. 물론 천천히 공부하면서 할 수도 있지만 워낙 성격이 급하고 빨리 돌아가는 것도 보고 싶은지라 그냥 익숙한 방식대로 했습니다.&lt;br /&gt;
&lt;br /&gt;
ITCSignal0는 어차피 필요한 타입 파라미터가 없기 때문에 템플릿 클래스가 아닌 그냥 일반 클래스로 정의했구요, ITCSignal1, ITCSignal2, ITCSignal3는 각각 인자의 타입 정보가 필요하므로 템플릿 클래스로 정의했습니다. 서로 다른 클래스이지만 모두 동일한 멤버 함수를 갖습니다. 먼저 가장 기본이 되는 ITCSignal0부터 살펴 보겠습니다.&lt;br /&gt;
&lt;br /&gt;
class ITCSignal0&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef boost::function&amp;lt;void ()&amp;gt; SlotType;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef const SlotType&amp;amp; ConnectionType;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ITCSignal0() : m_vec() {}&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename C&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ConnectionType connect(C* inst, void (C::*call)())&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return connect(boost::bind(call, inst));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename Caller, typename Callee = Caller&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; struct DoIt&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (Callee::*CallType)();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (Caller::*Type)(CallType);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename Caller, typename Callee&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ConnectionType connect(Caller* inst, &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; typename DoIt&amp;lt;Caller, Callee&amp;gt;::CallType call)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return connect(boost::bind(typename DoIt&amp;lt;Caller,Callee&amp;gt;::Type(&amp;amp;Caller::doIt), inst, call));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename C&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; struct FuncDoIt&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (*CallType)();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (C::*Type)(CallType);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename C&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ConnectionType connect(C* inst, typename FuncDoIt&amp;lt;C&amp;gt;::CallType call)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return connect(boost::bind(typename FuncDoIt&amp;lt;C&amp;gt;::Type(&amp;amp;C::doIt), inst, call));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ConnectionType connect(ConnectionType call)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; m_vec.push_back(call);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return m_vec[m_vec.size()-1];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; void disconnect(ConnectionType call)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; std::vector&amp;lt;SlotType&amp;gt;::iterator it = m_vec.begin();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for (;it != m_vec.end(); ++it)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (&amp;amp;(*it) == &amp;amp;call)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (it != m_vec.end())&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; m_vec.erase(it);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; void operator()()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; std::for_each(m_vec.begin(), m_vec.end(),&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; boost::mem_fn(&amp;amp;SlotType::operator()));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
private:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; std::vector&amp;lt;SlotType&amp;gt; m_vec;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
보시다시피 slot을 저장해두는 storage로는 그냥 SlotType(boost::function&amp;lt;void ()&amp;gt; type)의 vector를 사용하고 있습니다. 그냥 vector를 이용해서 connect(ConnectionType call)과 disconnect(ConnectionType call)을 구현하고 있습니다. 그런데, disconnect() 같은 경우, connect()의 리턴값을 기억하고 있다가 disconnect()를 호출하면 되니까 별 문제가 되지 않지만, connect(ConnectionType) 같은 경우 ConnectionType의 객체 인스턴스를 구성하는 것 자체가 무척 귀찮은 일입니다. boost::bind를 쓴다고 하더라도 상당한 수작업으로 인해 컴파일 에러가 많이 발생할 소지가 있습니다. 예를 들어, 다음과 같은 클래스가 선언되어 있는 상황에서&lt;br /&gt;
&lt;br /&gt;
struct Base&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; virtual void print()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; "Base::print()" &amp;lt;&amp;lt; endl;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Derived : public Base&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; virtual void print()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; "Derived::print()" &amp;lt;&amp;lt; endl;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct BaseITCAdaptor : public ITCAdaptor&amp;lt;Base&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BaseITCAdaptor(shared_ptr&amp;lt;Base&amp;gt; b, const string&amp;amp; name) :&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ITCAdaptor&amp;lt;Base&amp;gt;(b, name)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {}&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; void print()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; doIt(&amp;amp;Base::print);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
특정 BaseITCAdaptor 인스턴스에게 &amp;amp;Base::print 멤버 함수를 실행하게 하고 싶으면 다음과 같이 해야 합니다.&lt;br /&gt;
&lt;br /&gt;
BaseITCAdaptor* adpt = new BaseITCAdaptor(...);&lt;br /&gt;
ITCSignal0 sig;&lt;br /&gt;
&lt;font color="#193da9"&gt;&lt;strong&gt;sig.connect(boost::bind(&amp;amp;Base::print, adpt));&lt;br /&gt;
&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;
즉, boost::bind()를 사용해서 SlotType의 객체를 하나 만들어 줘야 합니다. 이렇게 할 경우, boost::bind() 사용법에 익숙해 져야해야 합니다. boost::bind에 익숙하지 않은 분은 위와 같은 코드를 작성하기 힘듭니다. 게다가, adpt 인자 위치와 &amp;amp;Base::print 인자 위치가 서로 바뀌었으면 좋겠더군요. 다음과 같이 할 수 있다면 훨씬 자연스럽게 느껴질 것 같더군요.&lt;br /&gt;
&lt;br /&gt;
sig.connect(adpt, &amp;amp;Base::print);&lt;br /&gt;
&lt;br /&gt;
adpt-&amp;gt;print() 하는 거랑 비슷하게 느껴지지 않으세요?&lt;br /&gt;
&lt;br /&gt;
ITCSignal3의 경우에는 코드가 더 복잡해 집니다. 다음과 같은 클래스가 선언되어 있다고 가정해 보겠습니다.&lt;br /&gt;
&lt;br /&gt;
struct ButtonHandler&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; void onClick3D(int x, int y, int z)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; "button clicked at (" &amp;lt;&amp;lt; x &amp;lt;&amp;lt; ", " &amp;lt;&amp;lt; y &amp;lt;&amp;lt; ", " &amp;lt;&amp;lt; z &amp;lt;&amp;lt; ")" &amp;lt;&amp;lt; endl;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
typedef ITCAdaptor&amp;lt;ButtonHandler&amp;gt; ButtonHandlerITCAdaptor;&lt;br /&gt;
&lt;br /&gt;
boost::bind를 써서 ITCSignal3와 onClick3D를 연결하려면 다음과 같이 작성해야 합니다.&lt;br /&gt;
&lt;br /&gt;
ITCSignal3&amp;lt;int, int, int&amp;gt;btnsig3;&lt;br /&gt;
btnsig3.connect(boost::bind(&lt;span style="color: rgb(227, 22, 0); font-weight: bold;"&gt;ITCSignal3&amp;lt;int,int,int&amp;gt;::DoIt&amp;lt;ButtonHandlerITCAdaptor, &lt;/span&gt;&lt;br style="color: rgb(227, 22, 0); font-weight: bold;"&gt;&lt;span style="color: rgb(227, 22, 0); font-weight: bold;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ButtonHandler&amp;gt;::Type(&amp;amp;ButtonHandlerITCAdaptor::doIt&amp;lt;int,int,int&amp;gt;)&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;btnHdlr, &amp;amp;ButtonHandler::onClick3D, _1, _2, _3));&lt;br /&gt;
&lt;br /&gt;
상당히 복잡하죠? 특히나 빨갛게 표시한 부분 때문에 눈이 휘둥그래지실 겁니다. 저렇게 복잡해진 이유는 ButtonHandlerITCAdaptor가 ITCAdaptor&amp;lt;ButtonHandler&amp;gt;로부터 상속을 받아 ButtonHandler::onClick3D를 wrapping하고 있는 멤버 함수를 따로 정의하고 있지 않기 때문입니다. 그래서 ButtonHandlerITCAdaptor::doIt&amp;lt;int,int,int&amp;gt; 멤버 함수를 btnsig3에 연결하되, &amp;amp;btnHandler 인스턴스 및 &amp;amp;ButtonHandler::onClick3D 멤버 함수를 추가적인 인자로 넘겨줘야 합니다. 그리고, 나중에 btnsig3를 발생시킬 때, int, int, int 세개를 인자를 받아들이기 위해 _1, _2, _3 를 써서 인자를 위한 자리를 마련해 둡니다. 이 생각을 그냥 코딩으로 옮긴다면, 다음만으로 충분할텐데,&lt;br /&gt;
&lt;br /&gt;
btnsig3.connect(boost::bind(&amp;amp;ButtonHandlerITCAdaptor::doIt&amp;lt;int,int,int&amp;gt;, &amp;amp;btnHdler,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;ButtonHandler::onClick3D, _1, _2, _3));&lt;br /&gt;
&lt;br /&gt;
왜 복잡하게 보이는 ITCSignal3&amp;lt;int,int,int&amp;gt;::DoIt&amp;lt;ButtonHandlerITCAdaptor, ButtonHandler&amp;gt;::Type 이런식으로 복잡한 형변환을 하고 있는 걸까요? 그건 doIt이 overload된 멤버 함수이기 때문입니다. 좀 더 상세히 설명하자면 overload된 멤버 함수는 단순히 이름만으로는 그 포인터를 얻어낼 수가 없기 때문에 그 타입 정보를 정확히 알려줘야 합니다. 예를 들어, 일반 함수가 다음과 같이 overload되어 있다면,&lt;br /&gt;
&lt;br /&gt;
void foo(int);&lt;br /&gt;
void foo(double);&lt;br /&gt;
&lt;br /&gt;
overload 된 함수 포인터를 얻어내기 위해서는 다음과 같이 코드를 작성해야 합니다.&lt;br /&gt;
&lt;br /&gt;
typedef void (*FuncType1)(int);&lt;br /&gt;
typedef void (*FuncType2)(double);&lt;br /&gt;
&lt;br /&gt;
FuncType1 fn1 = &amp;amp;foo;&lt;br /&gt;
FuncType2 fn2 = &amp;amp;foo;&lt;br /&gt;
boost::function&amp;lt;void (int)&amp;gt; f1 = FuncType1(&amp;amp;foo);&lt;br /&gt;
boost::function&amp;lt;void (double)&amp;gt; f2 = FuncType2(&amp;amp;foo);&lt;br /&gt;
&lt;br /&gt;
즉, l-value를 통해서 타입을 알려주던지 아니면 명시적 형변환을 사용해서 타입을 알려줘야 합니다. 그런데, &amp;amp;ButtonHandlerITCAdaptor::doIt&amp;lt;int,int,int&amp;gt; 이 멤버 함수의 타입을 그대로 풀어쓰면 이렇게 됩니다.&lt;br /&gt;
&lt;br /&gt;
void (ButtonHandlerITCAdaptor::*)(void (ButtonHandler::*)(int, int, int), int, int, int)&lt;br /&gt;
&lt;br /&gt;
말로 풀어쓰자면 int, int, int 인자를 갖고 리턴형식은 void인 ButtonHandler의 멤버 함수 포인터(void (ButtonHandler::*)(int, int, int))와 더불어 int, int, int 인자를 갖고 리턴형식은 void인 ButtonHandlerITCAdaptor의 멤버 함수 포인터입니다. 이해하기가 무척 어렵습니다. 이해를 돕기 위해 이걸 typedef를 이용해서 두 단계로 정의하면,&lt;br /&gt;
&lt;br /&gt;
typedef void (ButtonHandler::*CalleeMemFunPtr)(int, int, int);&lt;br /&gt;
typedef void (ButtonHandlerITCAdaptor::*CallerMemFunPtr)(CalleeMemFunPtr, int, int, int);&lt;br /&gt;
&lt;br /&gt;
가 되겠지요. 이걸 ITCSignal3&amp;lt;ArgType1, ArgType2, ArgType3&amp;gt;에 맞게 좀더 일반적으로 정의하기 위해 ITCSignal3 템플릿 클래스에 다음과 같은 typedef 를 정의했습니다.&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;typename ArgType1, typename ArgType2, typename ArgType3&amp;gt;&lt;br /&gt;
class ITCSignal3&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ......&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename Caller, typename Callee = Caller&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; struct DoIt&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (Callee::*&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;CallType&lt;/span&gt;)(ArgType1, ArgType2, ArgType3);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (Caller::*&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;Type&lt;/span&gt;)(&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;CallType&lt;/span&gt;, ArgType1, ArgType2, ArgType3);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ......&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
즉, ITCSignal3&amp;lt;ArgType1,ArgType2,ArgType3&amp;gt;::DoIt&amp;lt;Caller,Callee&amp;gt;::Type 을 정의한 것이지요. 이 Type이 다음과 같은 타입을 일반적으로 표현한 타입이 됩니다.&lt;br /&gt;
&lt;br /&gt;
void (ButtonHandlerITCAdaptor::*)(void (ButtonHandler::*)(int, int, int), int, int, int)&lt;br /&gt;
&lt;br /&gt;
그래서 다음과 같이 복잡한 표현이 나오게 된 것입니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: rgb(227, 22, 0); font-weight: bold;"&gt;ITCSignal3&amp;lt;int,int,int&amp;gt;::DoIt&amp;lt;ButtonHandlerITCAdaptor, &lt;/span&gt;&lt;br style="color: rgb(227, 22, 0); font-weight: bold;"&gt;&lt;span style="color: rgb(227, 22, 0); font-weight: bold;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ButtonHandler&amp;gt;::Type(&amp;amp;ButtonHandlerITCAdaptor::doIt&amp;lt;int,int,int&amp;gt;)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
위와 같이 일반적인 타입을 정의하고 나니, connect() 멤버 함수를 좀 더 편하면서도 타입 인자에 따라서 자동적으로 타입이 계산되게 만들 수 있었습니다.&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;typename ArgType1, typename ArgType2, typename ArgType3&amp;gt;&lt;br /&gt;
class ITCSignal3&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ......&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename Caller, typename Callee = Caller&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; struct DoIt&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (Callee::*CallType)(ArgType1, ArgType2, ArgType3);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; typedef void (Caller::*Type)(CallType, ArgType1, ArgType2, ArgType3);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename Caller, typename Callee&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ConnectionType &lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;connect(Caller* inst, &lt;/span&gt;&lt;br style="color: rgb(25, 61, 169); font-weight: bold;"&gt;&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; typename DoIt&amp;lt;Caller, Callee&amp;gt;::CallType call)&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;connect(boost::bind(typename DoIt&amp;lt;Caller,Callee&amp;gt;::Type(&lt;/span&gt;&lt;br style="color: rgb(25, 61, 169); font-weight: bold;"&gt;&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;Caller::template doIt&amp;lt;ArgType1, ArgType2, ArgType3&amp;gt;), &lt;/span&gt;&lt;br style="color: rgb(25, 61, 169); font-weight: bold;"&gt;&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; inst, call, _1, _2, _3));&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ......&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
위와 같이 connect() 멤버 함수를 정의하게 되면, 다음과 같이 좀 더 쉽게 boost::bind()를 쓰지 않고도 connect()를 호출할 수 있게 됩니다.&lt;br /&gt;
&lt;br /&gt;
btnsig3.connect&amp;lt;ButtonHandlerITCAdaptor, ButtonHandler&amp;gt;(&amp;amp;btnHdlr, &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;ButtonHandler::onClick3D);&lt;br /&gt;
&lt;br /&gt;
원래의 connect()&amp;nbsp; 멤버 함수를 사용할 때보다는 훨씬 간단해 졌습니다. 단, connect()에 타입 인자를 명시해야만 제대로 컴파일입니다.&lt;br /&gt;
&lt;br /&gt;
이 정도면 ITCSignal의 핵심적인 아이디어는 모두 설명드린 것 같습니다. 다른 클래스 및 멤버 함수들은 이 글에서 설명드린 내용의 반복이기 때문에 자세한 설명은 생략하도록 하겠습니다.&lt;br /&gt;
&lt;br /&gt;
다음 개선사항으로는 리턴값이 있는 함수를 지원하는 기능을 추가해 볼 생각입니다.&lt;br /&gt;
&lt;br /&gt;
혹시 잘못된 부분이나 개선사항이 있으시면 얘기 좀 해주세요~ &lt;br /&gt;
&lt;br /&gt;
여느때와 같이 코드 첨부합니다. 이해되지 않는 부분에 대한 질문도 환영합니다. ^^&lt;br /&gt;
&lt;br /&gt;
&lt;table style="display: inline; border-collapse: collapse"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://yesarang.tistory.com/attachment/491d976f79b029P.gz"&gt;&lt;img src="http://cfs.tistory.com/blog/image/extension/gz.gif" alt="" style="vertical-align: middle;" /&gt; itc.v10.tar.gz&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2056854" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/E1XHpHwiZj8" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<category>c++</category>
			<category>itc</category>
			<category>Programming</category>
			<category>sw개발</category>
			<category>프로그래밍</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/341</guid>
			<comments>http://yesarang.tistory.com/341#entry341comment</comments>
			<pubDate>Wed, 12 Nov 2008 23:05:01 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/341</feedburner:origLink></item>
		<item>
			<title>C++이야기 스물다섯번째: 구현이 없는 가상함수는 반드시 순수가상함수로!</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/hk1TRrCNg5Y/340</link>
			<description>&lt;a href="http://yesarang.tistory.com/332" target="_blank"&gt;2008/10/31 - [S/W개발/C++ 이야기] - C++이야기 스물네번째: Override할 가상함수의 Prototype은 확인 또 확인!&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
이번 글도 저번글에 이어 C++로 프로그래밍하다가 저지르기 쉬운 실수입니다. 이번에도 바로 코드부터 보겠습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;/// @file virtual.cpp&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;using namespace std;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;class Base&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; virtual void hello(const string&amp;amp; name);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;class Derived : public Base&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; virtual void hello(const string&amp;amp; name)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; "Hello, " &amp;lt;&amp;lt; name &amp;lt;&amp;lt; "!" &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;int&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;main()&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Base* p = new Derived();&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; p-&amp;gt;hello("KKK");&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이 코드를 컴파일해서 실행시키면 어떤 결과가 출력될까요? 이번에도 함정이 숨어 있으니 코드를 잘 주의해서 보시기 바랍니다. 당연히 "Hello, KKK!"라고 출력될까요? 그렇다면 제가 문제를 내지도 않았겠지요?&lt;br /&gt;
&lt;br /&gt;
정답은 바로 바로&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
"링크시에 에러가 발생한다"였습니다. 엥? 하시면서 눈을 마구 굴리시는 분이 보이는군요. ^___^&lt;br /&gt;
&lt;br /&gt;
Visual C++ 2005 Express로 컴파일했더니 다음과 같은 에러가 발생하네요.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;virtual.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Base::hello(class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt; const &amp;amp;)" (?hello@Base@@UAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;C:\Documents and Settings\김윤수\My Documents\Visual Studio 2005\Projects\virtual\Debug\virtual.exe : fatal error LNK1120: 1 unresolved externals&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
다시 잘 해석해 보자면 Base::hello() 멤버 함수가 정의되어 있질 않다는 거네요. Derived::hello()를 정의해 놓았으니 p-&amp;gt;hello() 하면 Derived::hello() 하고 링크되는 거 아닌가? 왜 Base::hello()를 찾지??? 하면서 의아해 하시는 분들이 있는 것 같네요.&lt;br /&gt;
&lt;br /&gt;
Base::hello()는 위 소스코드에서는 사용되진 않지만 실제로는 Base의 virtual function table(vtbl 이라고도 하죠)을 채워넣을 때, Base::hello()를 참조하게 됩니다. Base::hello()를 선언할 때 순수가상함수로 선언하지 않았기 때문이지요.&lt;br /&gt;
&lt;br /&gt;
소스코드에서는 Base::hello()가 한 번도 사용되진 않지만 컴파일러가 내부적으로 생성하는 데이터 구조(vtbl)에서는 Base::hello()를 참조하고 있기 때문에 unresolved symbol에러가 발생하는 것입니다. 실제로 Base::hello()의 구현을 추가한 후, Visual C++ 디버거에서 확인하면 다음과 같이 Base 클래스와 Derived 클래스에 대해 각각 vtbl을 생성한 것을 볼 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;img src="http://cfs10.tistory.com/image/1/tistory/2008/11/12/01/09/4919ae4e648a6" alt="" filemime="" filename="vtbl.PNG" height="190" width="510"/&gt;&lt;/div&gt;&lt;br /&gt;
이런 버그도 프로젝트 규모가 커지다 보면 아주 간단한 실수임에도 찾기가 무척 어렵습니다. 왜냐면 사람눈에는 문제가 잘 보이지 않기 때문이죠. 컴파일러 내부적으로 vtbl을 구성할 때, 순수가상함수로 선언되어 있지 않은 것들은 모두 포함된다라는 사실을 알고 있어야 하고, 거기에 덧붙여&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;class Base&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; virtual void hello(const string&amp;amp; name) &lt;span style="color: rgb(227, 22, 0); font-weight: bold;"&gt;= 0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 또는&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; virtual void hello(const string&amp;amp; name) &lt;span style="color: rgb(227, 22, 0); font-weight: bold;"&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
빨갛게 표시한 부분을 빼먹었다는 걸 알아챌 수 있어야 합니다. 그런데 아주 근소한 차이이기 때문에 찾기가 무척 힘듭니다.&lt;br /&gt;
&lt;br /&gt;
그러니 이런 버그 찾으려고 몇 시간씩 헤매지 마시고 코딩할 때 항상 &lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: rgb(25, 61, 169); font-weight: bold;"&gt;"구현이 없는 가상함수는 순수가상함수로 선언"&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
하는 습관을 들이시면 좋을 것입니다. 만약 순수한 인터페이스를 선언할 의도가 아니었다면 가상함수를 반드시 구현해야 할 것입니다.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  				&lt;embed src="http://api.v.daum.net/static/recombox1.swf?nid=2041956" quality="high" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/hk1TRrCNg5Y" height="1" width="1"/&gt;</description>
			<category>C++ 이야기</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/340</guid>
			<comments>http://yesarang.tistory.com/340#entry340comment</comments>
			<pubDate>Wed, 12 Nov 2008 01:19:31 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/340</feedburner:origLink></item>
		<item>
			<title>김윤수의 인터넷 오늘은 - 2008년 11월 8일</title>
			<link>http://feedproxy.google.com/~r/yoonsookim/~3/NSkoWzmwvxw/339</link>
			<description>&lt;div class="me2day_daily_digest"&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href='http://me2day.net/yesarang/2008/11/08#00:01:42'&gt;이 문제&lt;/a&gt;가 발생했던 이유는 제가 잘못한 게 아니라 g++ 4.0.1이 &lt;a href='http://gcc.gnu.org/ml/gcc/2006-10/msg00573.html'&gt;pointer to template member function 과 관련된&lt;/a&gt; &lt;a href='http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407'&gt;버그&lt;/a&gt;가 있어서 그렇더군요. 4.2.0까지는 이 문제가 해결되지 않았나 보더군요. 4.2.1은 되는 것 같은데…&lt;span class="me2_tags"&gt;(SW개발 ITC inter thread communication C++ programming cpp g++ 버그 pointer to template member function)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/08#18:06:43" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-08 18:06:43&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;

      &lt;li&gt;&lt;a href='http://me2day.net/yesarang/2008/11/07#19:59:23'&gt;ITCSignal&lt;/a&gt; 대강 구현했다. 그런데 쓰기가 너무 불편해. 어떡하면 쓰기 쉽게 만들 수 있을까? connect 를 template member function으로 만들어서 argument matching이 알아서 되게 하면 되나?&lt;span class="me2_tags"&gt;(SW개발 ITC inter thread communication C++ programming cpp ITCSignal)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/08#18:13:49" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-08 18:13:49&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;

      &lt;li&gt;ITCSignal 쉽게 쓸 수 있도록 connect를 template member function으로 구현하고 있는데 반복되는 코드가 너무 많다. 눈이 어질 어질…&lt;span class="me2_tags"&gt;(SW개발 ITC inter thread communication C++ programming cpp ITCSignal)&lt;/span&gt;&lt;span class="datetime"&gt;&lt;a href="http://me2day.net/yesarang/2008/11/08#22:05:23" rel="bookmark" title="퍼머링크" class="datetime"&gt;2008-11-08 22:05:23&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;

    &lt;/ul&gt;
    &lt;p style="background:url(http://me2day.net/images/me2day_icon.gif) no-repeat right top;padding-right:25px;text-align:right; font-size: 0.9em;"&gt;이 글은 &lt;a href="http://me2day.net/yesarang" target="_blank"&gt;김윤수&lt;/a&gt;님의 &lt;a href="http://me2day.net/yesarang/2008/11/08#18:06:43"&gt;2008년 11월 8일&lt;/a&gt;의 미투데이 내용입니다.&lt;/p&gt;
  &lt;/div&gt; &lt;!-- end of daily_digest --&gt;&lt;img src="http://feeds.feedburner.com/~r/yoonsookim/~4/NSkoWzmwvxw" height="1" width="1"/&gt;</description>
			<category>인터넷오늘은</category>
			<category>c</category>
			<category>communication</category>
			<category>cpp</category>
			<category>function</category>
			<category>G</category>
			<category>Inter</category>
			<category>itc</category>
			<category>itcsignal</category>
			<category>member</category>
			<category>Pointer</category>
			<category>Programming</category>
			<category>sw개발</category>
			<category>Template</category>
			<category>thread</category>
			<category>to</category>
			<category>버그</category>
			<author>김윤수</author>
			<guid isPermaLink="false">http://yesarang.tistory.com/339</guid>
			<comments>http://yesarang.tistory.com/339#entry339comment</comments>
			<pubDate>Sun, 09 Nov 2008 04:31:53 +0900</pubDate>
		<feedburner:origLink>http://yesarang.tistory.com/339</feedburner:origLink></item>
	</channel>
</rss>
