<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>센로그</title>
    <link>https://grace7040.tistory.com/</link>
    <description>KyungHee University - Department of Software Convergence </description>
    <language>ko</language>
    <pubDate>Sun, 9 Aug 2026 02:12:15 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>seeyoun</managingEditor>
    <image>
      <title>센로그</title>
      <url>https://tistory1.daumcdn.net/tistory/5607021/attach/c17985aac0ce4cb38da0720773123e01</url>
      <link>https://grace7040.tistory.com</link>
    </image>
    <item>
      <title>[ED] 27. 독립적인 프로세스로 구성된 시스템에서 모니터링 도구 사용하기</title>
      <link>https://grace7040.tistory.com/386</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;요즘 소프트웨어 시스템 중에서 단 하나의 프로그램으로만 구성된 것은 거의 없다.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대부분의 시스템을 여러 서비스와 컴포넌트, 라이브러리로 구성되어 있다.&lt;/li&gt;
&lt;li&gt;따라서 어느 부분에서 오류가 발생했는지 신속하고 효율적으로 알아내는 것이 중요하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;서버 시스템에서는 인프라스트럭처 모니터링 시스템을 구축하면 문제의 발생 지점을 쉽게 찾을 수 있다.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모니터링 환경을 구축하여 개발하고자 하는 서비스에 관련된 모든 부분의 상태를 지속적으로 확인한다.&lt;/li&gt;
&lt;li&gt;책에서는 Nagios를 소개하지만, 좀더 대규모 서버를 모니터링하기에 적합한 현대적인 모니터링 시스템들이 되게 많다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Zabbix&lt;/li&gt;
&lt;li&gt;Prometheus + Grafana&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;암튼 모니터링 방법은!&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;발생한 문제를 정확히 집어내려면 애플리케이션을 구성하는 스택 전체를 모니터링해야 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 먼저 시스템을 구성하는 호스트에서 가장 낮은 레벨에 해당하는 자원의 상태부터 모니터링한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU 부하량, 메모리 사용량, 네트워크 도달 가능성, 실행 중인 프로세스 및 로그인한 사용자 수, 가용한 소프트웨어 업데이트, 디스크 여유 공간, 사용 중인 네트워크 및 디스크 대역폭, 시스템 로그, 보안, 원격 접속 ...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이후 애플리케이션 구동에 필요한 서비스들을 모니터링한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스, 이메일 서버, 애플리케이션 서버, 캐시, 네트워크 연결, 백업, 큐, 메시징, 소프트웨어 라이선스, 웹 서버, 디렉토리 서비스 ...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;마지막으로 애플리케이션의 상태를 상세히 모니터링 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어플리케이션의 엔드 투 엔드(end-to-end) 가용성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) 웹 폼을 완성하면 전체 트랜잭션을 완성하는지 여부&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;웹 서비스, 데이터베이스 테이블, 정적 웹 페이지, 인터랙티브 웹 폼, 리포팅 서비스 등과 같이 어플리케이션을 구성하는 요소들&lt;/li&gt;
&lt;li&gt;응답 지연 시간, 큐에 저장되거나 완료된 명령, 활동 중인 사용자의 수, 실패한 트랜잭션, 발생한 에러, 리포팅 된 충돌 사항 등과 같이 핵심적인 측정 지표&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장애가 발생하는 즉시 알림을 보내도록 설정하면 에러가 나타난 상태에서 디버깅 작업을 수행할 수 있다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원하는 알림 기능을 현재 사용하는 모니터링 시스템에서 제공하지 않는다면, 알림을 제공하는 코드를 작성하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오류 발생 내역을 분석하면 문제의 원인을 정확히 찾아내는 데 도움되는 패턴을 도출할 수 있다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;장애가 어디서 발생했는지 면밀히 분석하다 보면 장애를 유발한 다양한 요인들을 밝혀낼 수 있다.&lt;/li&gt;
&lt;li&gt;전체 스택을 모니터링하다 보면 스택의 아랫단에서 발생한 장애가 위로 전파되면서 다른 형태의 문제를 일으키는 경우도 볼 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이럴 때는 문제가 발생한 요소 중 가장 로우 레벨에 있는 것부터 분석하는 것이 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Effective/Effective Debugging</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/386</guid>
      <comments>https://grace7040.tistory.com/386#entry386comment</comments>
      <pubDate>Tue, 19 Nov 2024 01:26:54 +0900</pubDate>
    </item>
    <item>
      <title>[ED] 26. 버전 관리 시스템으로 버그 원인과 히스토리 추적하기</title>
      <link>https://grace7040.tistory.com/385</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;버전 관리 시스템에 기록된 파일의 변경 내역을 분석하면 버그가 언제 어떻게 생겼는지 알아낼 수 있다.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #515151; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버전 관리 시스템을 활용하여 정상적인 버전과 버그가 있는 버전을 비교한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;버그 분석에 유용한 깃 명령어들&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #515151; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;새로운 버그를 발견했다면 먼저 이전 버전에서 어떤 부분을 변경했는지 살펴본다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;git log&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;발생한 문제와 관련된 파일을 찾았다면 그 파일에 대한 변경 사항만 자세히 살펴본다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;git log&lt;/b&gt; path/to/myfile.js&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;발생한 문제가 코드의 특정 라인에 관련되어 있다고 의심되면, 해당 코드에 대한 어노테이션 정보를 출력해서 각 라인에서 가장 최근 발생한 변경 사항을 자세히 살펴본다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;git blame&lt;/b&gt; path/to/myfile.js&lt;/li&gt;
&lt;li&gt;해당 파일 내부 또는 여러 파일 사이에서 이동한 라인을 추적하려면 -C와 -M 옵션을 지정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;문제와 관련된 부분이 코드에서 삭제됐다면 과거에 삭제된 내용을 뒤져본다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;git rev-list&lt;/b&gt; -all | &lt;b&gt;xargs git grep&lt;/b&gt; 삭제된_메서드_이름&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;문제가 발생하기 바로 전 버전을 알고 있다면 그 버전 이후에 변경된 내역을 살펴본다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가령 V1.2.3 이후에 문제가 발생했다면 다음과 같이 실행한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;git log&lt;/b&gt; V1.2.3..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;어느 버전인지는 정확히 모르지만 해당 문제가 발생한 날짜는 알고 있다면 그 날짜 바로 전에 커밋한 SHA 해시를 알아낸다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;git rev-list&lt;/b&gt; -n 1 --before=2015-08-01 maseter&lt;/li&gt;
&lt;li&gt;이렇게 구한 SHA 해시를 버전 문자열 대신 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;문제가 특정한 이슈를 해결한 뒤에 발생했다면 해당 이슈에 관련된 모든 커밋을 검색한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가령 이슈 1234번을 해결한 커밋의 메시지에 'Issue #1234'라는 문자열이 담겨 있다면 다음 명령을 실행한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;git log&lt;/b&gt; -all --grep='Issue #1234'&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;살펴보려는 커밋에 대한 SHA 해시를 알고 있다면 해당 커밋에서 변경한 내역을 살펴볼 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가령 살펴보려는 커밋의 해시가 1cb6e3f6이라면 다음 명령을 실행한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;git show&lt;/b&gt; 1cb6e3f6&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;두 버전 사이에 일어난 변경 사항을 보려면 다음과 같이 실행한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;git diff&lt;/b&gt; V1.2.3..V1.3.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #515151; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가령 버그가 발생한 버전의 구간을 알고 있고, 오류가 발생하면 0이 아닌 코드를 반환하며 종료하는 테스트 스크립트도 있다면, 그 버전 사이에서 발생한 모든 변경 내역을 이진 탐색으로 검색해서 해당 버그를 발생시킨 지점을 찾아준다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;git bisect&lt;/b&gt; start V1.1.0 V1.2.3 &lt;br /&gt;&lt;b&gt;git bisect&lt;/b&gt; run test.sh &lt;br /&gt;&lt;b&gt;git reset&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Effective/Effective Debugging</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/385</guid>
      <comments>https://grace7040.tistory.com/385#entry385comment</comments>
      <pubDate>Tue, 19 Nov 2024 01:07:26 +0900</pubDate>
    </item>
    <item>
      <title>[ED] 25. 작업 환경 최적화하기</title>
      <link>https://grace7040.tistory.com/384</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용하는 도구를 적절히 설정하여 생산성을 향상시킨다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어 배시 명령과 관련된 설정 사항을 몇가지 소개하면 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #515151; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;PATH 환경 변수&lt;/b&gt;에 실행할 프로그램에 관련된 디렉터리가 빠짐없이 담겨 있는지 확인한다. 디버깅 과정에서 시스템 관리자 권한의 명령을 실행해야 하는 경우도 종종 있다. 따라서 이러한 명령에 대한 경로도 포함해야 한다.&lt;/li&gt;
&lt;li&gt;쉘과 편집기에서 &lt;b&gt;자동 완성 기능&lt;/b&gt;을 사용하도록 설정한다.&lt;/li&gt;
&lt;li&gt;쉘 프롬프트와 터미널 바에 &lt;b&gt;사용자 계정과 현재 디렉터리, 호스트 이름&lt;/b&gt;이 표시되도록 설정한다. 디버깅하는 과정에서 여러 호스트와 계정을 오갈 수 있기 때문에 현재 상태를 명확히 알 수 있도록 계정과 위치 정보를 표시한다.&lt;/li&gt;
&lt;li&gt;명령줄에서 편집할 때 자신이 사용할 편집기와 연동하도록 &lt;b&gt;키 바인딩&lt;/b&gt;을 설정한다. 이렇게 해두면 데이터 분석 파이프라인을 점진적으로 만들어나가는 작업을 훨씬 효율적으로 수행할 수 있다.&lt;/li&gt;
&lt;li&gt;자주 사용하는 명령과 흔히 저지르는 입력 오류에 대해 &lt;b&gt;앨리어스나 단축키&lt;/b&gt;를 만든다.&lt;/li&gt;
&lt;li&gt;버전 관리 시스템을 비롯한 다양한 유틸리티에서 자신이 주로 사용하는 페이징 프로그램(less나&lt;span&gt;&amp;nbsp;&lt;/span&gt;more처럼 파일의 내용을 페이지 단위로 출력하는 프로그램)과 편집기를 활용하도록 환경변수를 설정한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;입력한 명령을 모두 히스토리 파일에 기록&lt;/b&gt;하도록 설정한다. 이렇게 하면 디버깅할 때 자주 사용하거나 중요한 구문을 몇 달이 지난 뒤에도 쉽게 찾아낼 수 있다. 이때 구문 앞에 공백을 붙여서 (패스워드를 담은 부분처럼) 명령을 호출하는 부분은 기록하지 않도록 설정한다.&lt;/li&gt;
&lt;li&gt;쉘의 경로 이름 확장 기능 또는 *과 같은 와일드카드 문자로 표현하는 글로빙(globbing)을 실행할 때 서브 디렉터리에 있는 파일도 포함하도록 설정한다. 이렇게 하면 하위 계층에 있는 모든 디렉터리에 대해 적용되는 ** 와일드 카드를 사용할 수 있기 때문에, 계층이 깊게 구성된 디렉터리에 대해 실행하는 명령을 간결하게 작성할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;여러 호스트에 걸쳐 작업할 때는 디버깅 환경에 대한 설정 파일을 버전 관리 시스템을 통해 추적한다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 경우에는 다음 세가지 설정을 통해 작업 시간을 크게 절약할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;패스워드를 입력하지 않고도 각각의 호스트에 원격에서 로그인하거나 명령을 실행하도록 한다.&lt;/li&gt;
&lt;li&gt;사용자 이름 뒤에 호스트의 전체 이름을 입력하지 않고 짧은 이름만으로 호스트에 접속하도록 앨리어스를 설정한다.&lt;/li&gt;
&lt;li&gt;원격 호스트에서 구동한 &lt;b&gt;GUI 애플리케이션&lt;/b&gt;을 현재 작업하는 데스크톱에 표시하도록 설정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Effective/Effective Debugging</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/384</guid>
      <comments>https://grace7040.tistory.com/384#entry384comment</comments>
      <pubDate>Tue, 19 Nov 2024 00:56:57 +0900</pubDate>
    </item>
    <item>
      <title>[ED] 24. 코드 편집기(IDE)로 디버깅 데이터 탐색하기</title>
      <link>https://grace7040.tistory.com/383</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;철자가 틀린 식별자를 찾을 때는 편집기에서 제공하는 검색 기능을 활용한다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대부분의 IDE는 식별자를 검색하면 같은 같은 부분을 찾아주므로 단어가 나타난 지점을 탐색하기 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;차이점이 눈에 띄도록 텍스트파일을 적절히 수정한다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;diff와 같은 도구를 활용할 수도 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;핵심과 관련 없는 부분을 모두 일정 문자로 치환하면 diff로 작업하기 쉬워진다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IP 주소, 타임 스탬프 등 문제의 핵심과 관련 없는 부분들을 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;로그 파일을 좀 더 읽기 좋도록 적절히 수정한다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;불필요한 부분을 삭제하고 원하는 내용만 남긴다.&lt;/li&gt;
&lt;li&gt;로그 파일 내용이 너무 복잡해서 한눈에 들어오지 않는다면 부연 설명을 주석으로 추가하는 것도 도움이 된다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Effective/Effective Debugging</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/383</guid>
      <comments>https://grace7040.tistory.com/383#entry383comment</comments>
      <pubDate>Tue, 19 Nov 2024 00:48:38 +0900</pubDate>
    </item>
    <item>
      <title>[ED] 23. 명령줄 도구 옵션과 관용 표현 활용하기</title>
      <link>https://grace7040.tistory.com/382</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;grep에서 제공하는 다양한 옵션을 활용하면 탐색 범위를 줄일 수 있다.&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;453&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccq0Cw/btsKMY4wKlg/MY7Hzuq0z8mNus1iBowGsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccq0Cw/btsKMY4wKlg/MY7Hzuq0z8mNus1iBowGsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccq0Cw/btsKMY4wKlg/MY7Hzuq0z8mNus1iBowGsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fccq0Cw%2FbtsKMY4wKlg%2FMY7Hzuq0z8mNus1iBowGsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;453&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로그램의 에러 메시지를 분석할 때는 표준 에러를 리다이렉션한다.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;에러 메시지는 표준 출력으로 보내는 게 아니라 표준 에러로 보내도록 하는 것이 관례이다.&lt;/li&gt;
&lt;li&gt;표준 출력과 섞이면 처리하는 프로그램도 헷갈리고 보기도 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;로그 파일에 추가되는 내용을 모니터링하고 싶다면 tail -f 명령을 활용한다.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디버깅하려는 에러가 아주 가끔 발생한다면, 해당 에러가 발생하는 즉시 알려주는 모니터링 환경을 구축하는 것이 좋다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Effective/Effective Debugging</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/382</guid>
      <comments>https://grace7040.tistory.com/382#entry382comment</comments>
      <pubDate>Tue, 19 Nov 2024 00:04:05 +0900</pubDate>
    </item>
    <item>
      <title>[ED] 22. 유닉스 명령줄 도구로 디버깅 데이터 분석하기</title>
      <link>https://grace7040.tistory.com/381</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;여러 가지 유닉스 명령을 파이프라인으로 조합하는 방식으로 복잡한 분석 작업을 간단히 처리할 수 있다.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #515151; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디버깅 과정에서 다루는 데이터는 대부분 텍스트 포맷으로 되어 있기 때문에 사용하는 도구의 표준 입력으로 데이터를 그대로 전달할 수 있다.&lt;/li&gt;
&lt;li&gt;텍스트를 분석할 때 여러 유닉스 명령을 파이프라인으로 조합하여 사용한다.&lt;/li&gt;
&lt;li&gt;일반적으로 다음 순서로 스크립트를 작성하면 된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가져오기(Fetching)&lt;/li&gt;
&lt;li&gt;선택하기(Selecting)&lt;/li&gt;
&lt;li&gt;처리하기(Processing)&lt;/li&gt;
&lt;li&gt;정리하기(Summarizing)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;자주 쓰이는 유닉스 명령어&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;grep&lt;/b&gt;:&lt;br /&gt;텍스트 파일에서 특정 문자열 또는 패턴을 검색하고 일치하는 줄을 출력&lt;/li&gt;
&lt;li&gt;&lt;b&gt;find&lt;/b&gt;:&lt;br /&gt;디렉터리 트리에서 파일이나 디렉터리를 이름, 크기, 수정 시간 등 다양한 조건으로 검색&lt;/li&gt;
&lt;li&gt;&lt;b&gt;awk&lt;/b&gt;:&lt;br /&gt;텍스트 데이터를 행(row)과 열(column) 단위로 처리 및 변환하며, 특정 열을 추출하거나 계산 작업에 사용됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;sort&lt;/b&gt;:&lt;br /&gt;텍스트 파일의 내용을 알파벳 순, 숫자 순 등으로 정렬&lt;/li&gt;
&lt;li&gt;&lt;b&gt;head&lt;/b&gt;:&lt;br /&gt;파일의 처음 몇 줄을 출력(기본적으로 첫 10줄).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;처리하기 힘든 포맷으로 구성되어 있다면 그 포맷을 지원하는 도구를 사용한다.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를들어 C++ 프로그램이 갑자기 종료했다면, 해당 오브젝트 파일을 nm(유닉스) 명령으로 실행하여 exit 함수가 호출된 지점을 찾을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Effective/Effective Debugging</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/381</guid>
      <comments>https://grace7040.tistory.com/381#entry381comment</comments>
      <pubDate>Mon, 18 Nov 2024 23:57:34 +0900</pubDate>
    </item>
    <item>
      <title>[EC++] 13. 자원 관리에는 객체가 그만!</title>
      <link>https://grace7040.tistory.com/380</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;delete는 항상 호출될 것인가?&lt;/h2&gt;
&lt;pre id=&quot;code_1731936624490&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Investment { ... };

Investment* createInvestment();		// Investment 계통에 속한 클래스의 객체를 동적할당하고 그 포인터를 반환

void f() {
    Investment* pInv = createInvestment();
    ...
    delete pInv;
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 코드에서 delete pInv; 가 항상 호출될 것이라고 믿으면 안된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;... 부분에 return 문이 있다면?&lt;/li&gt;
&lt;li&gt;... 부분에서 예외가 던져진다면?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;delete 문이 실행되지 않게 된다면, 객체를 담고 있는 메모리가 누출되며, 객체가 갖고 있던 자원도 모두 누수된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;자원이 항상 해제되도록 만들 수는 없을까?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자원을 객체에 넣고, 그 &lt;b&gt;&lt;i&gt;자원 해제를 소멸자&lt;/i&gt;&lt;/b&gt;가 맡도록 하며, 소멸자는 로컬 스코프를 떠날때 호출되도록 만들면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;예시 상황&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(C++ 17 이후로 auto_ptr은 사라졌지만, 일단 책에서 제시한 예제를 그대로 사용하기로 함.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 위 코드에서 pInv 포인터를 std::auto_ptr로 만들면 어떨까?&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 방법에는 다음 두가지 특징이 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자원을 획득하고 나서 바로 자원 관리 객체에게 넘겨준다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RAII: 자원의 획득은 객체의 초기화와 동일하다. (Resource Acquisition Is Initialization)&lt;/li&gt;
&lt;li&gt;자원을 소유하고 관리하는 객체를 생성할 때 해당 자원을 초기화하고, 객체가 소멸될 때 자원을 자동으로 해제하도록 설계하는 방식이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;자원 관리 객체는 자신의 소멸자를 사용해서 자원이 확실히 해제되도록 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체는 스코프가 끝나면 소멸되므로, 자원은 스코프를 벗어나면 자동으로 해제된다.&lt;/li&gt;
&lt;li&gt;즉, 실행 제어가 어떤 경위로 스코프를 떠나는가에 상관 없이 자동으로 자원 해제가 이루어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;auto_ptr을 쓰기 힘든 상황이라면 shared_ptr을 고민해봐도 좋다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참조 카운팅 방식으로, 참조가 0이 되면 자원을 해제한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스마트 포인터로 배열 다룰 때 주의할 점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예전에는 동적 배열을 스마트포인터로 가리키면 안됐다.&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소멸자에 정의된 delete가 delete[]가 아니었기 때문이었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;근데 요즘은 되는 듯.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커스텀 소멸자 정의할 수 있다. 거기다가 delete[]로 넣으면 된다.&lt;/li&gt;
&lt;li&gt;또는, 애초에 타입 받을 때 배열 형태(T[]) 로 받으면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;추가&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;+) auto_ptr vs unique_ptr&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;std::unique_ptr은 std::auto_ptr의 기능을 현대적이고 안전하게 대체하기 위해 설계되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 차이점은 다음과 같다:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;257&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbzQvQ/btsKOAuuv9y/kYehDXaApkjDtubptGBvk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbzQvQ/btsKOAuuv9y/kYehDXaApkjDtubptGBvk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbzQvQ/btsKOAuuv9y/kYehDXaApkjDtubptGBvk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbzQvQ%2FbtsKOAuuv9y%2FkYehDXaApkjDtubptGBvk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;257&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;257&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;+)&lt;span&gt; unique_ptr이 상대적으로 스레드세이프한 이유는?&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;auto_ptr의 경우 복사 시 소유권이 전이되는 형태이며, 암묵적으로 소유권이 전이된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복사가 허용되면, 여러 스레드에서 동일한 auto_ptr을 복사하려고 할 때 Race Condition이 발생하기 매우 쉽다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;unique_ptr은 std::move를 통해 명시적으로 소유권을 전이한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여전히 Race Condition이 발생할 수 있지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;명시적인 이동 설계 덕분에 이를 더 쉽게 관리할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;물론 둘 다 완전히 스레드세이프하지는 않다. 그러나 unique_ptr이 좀 더! 낫다는 거다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;+) 왜 std::auto_ptr에서 std::unique_ptr로 바뀌었는가?&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;복사 시 소유권 전이의 문제&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;std::auto_ptr은 복사 시 소유권이 이동되기 때문에, 예기치 않은 동작을 유발할 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이는 코드의 직관성을 떨어뜨리고, 의도하지 않은 메모리 해제를 초래할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;std::unique_ptr은 복사를 금지하고, 소유권 이동만 허용함으로써 이 문제를 해결했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스레드 안전성&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;std::auto_ptr은 멀티스레드 환경에서 사용하기에 적합하지 않았다.&lt;/li&gt;
&lt;li&gt;std::unique_ptr은 이동 시점을 명확히 지정하고, 불필요한 동기화 문제를 줄였다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;커스터마이징 가능성&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;std::unique_ptr은 커스텀 해제 함수(Deleter)를 지정할 수 있어 더 유연하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1731937529665&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;std::unique_ptr&amp;lt;int, void(*)(int*)&amp;gt; ptr(new int(42), [](int* p) { std::cout &amp;lt;&amp;lt; &quot;Deleting &quot; &amp;lt;&amp;lt; *p &amp;lt;&amp;lt; std::endl; delete p; });&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;현대적인 메모리 관리 패턴과의 호환성&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;C++11에서 도입된 이동 시맨틱(move semantics)와 더 잘 어울린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Effective/Effective C++</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/380</guid>
      <comments>https://grace7040.tistory.com/380#entry380comment</comments>
      <pubDate>Mon, 18 Nov 2024 23:31:33 +0900</pubDate>
    </item>
    <item>
      <title>[EC++] 12. 객체의 모든 부분을 빠짐없이 복사하자</title>
      <link>https://grace7040.tistory.com/379</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;커스텀 복사 생성자 및 복사 대입 연산자 구현 시 주의할 점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 데이터 멤버들을 빠짐없이 복사해야 한다.&lt;/li&gt;
&lt;li&gt;빠진 요소가 있더라도 컴파일러가 친절하게 알려주지는 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예시 상황&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 고객을 나타내는 Customer 클래스가 있다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731934784568&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void logCall(const string&amp;amp; funcName);

class Customer {
public:
    ...
    Customer(const Customer&amp;amp; rhs);
    Customer&amp;amp; operator=(const Customer&amp;amp; rhs);
    ...
private:
    string name;
};

Customer::Customer(const Customer&amp;amp; rhs) : name(rhs.name) {
    logCall(&quot;Customer Copy Constructor&quot;);
}

Customer&amp;amp; Customer::operator=(const Customer&amp;amp; rhs) {
    logCall(&quot;Customer Copy Assignment Operator&quot;);
    name = rhs.name;
    return *this;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커스텀 복사 생성자와 복사 대입연산자를 구현하였다.&lt;/li&gt;
&lt;li&gt;문제 없이 잘 돌아간다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 그러나 이때 데이터 멤버 하나를 더 추가한다면?&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731934910060&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Date { ... };
class Customer {
public:
    ...
private:
    string name;
    Date lastTransaction;
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;멤버가 추가되더라도 기존 복사 생성자와 복사 대입 연산자는 별도의 오류 없이 그대로 동작한다.&lt;/li&gt;
&lt;li&gt;즉, 객체의 전체가 아닌 일부만 복사하는 바보 함수가 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 가장 문제되는 상황은 상속에서의 상황이다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731935049487&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class PriorityCustomer : public Customer {
public:
    ...
    PriorityCustomer(const PriorityCustomer&amp;amp; rhs);
    PriorityCustomer&amp;amp; operator=(const PriorityCustomer&amp;amp; rhs);
    ...
private:
    int priority;
};

PriorityCustomer::PriorityCustomer(const PriorityCustomer&amp;amp; rhs) : priority(rhs.priority) {
    logCall(&quot;Priority Customer Copy Consturctor&quot;);
}

PriorityCustomer&amp;amp; PriorityCustomer::operator=(const PriorityCustomer* rhs) {
    logCall(&quot;Priority Customer Copy Assignment Operator&quot;);
    priority = rhs.priority;
    return *this;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Customer을 상속받는 PriorityCustomer 클래스가 있다.&lt;/li&gt;
&lt;li&gt;PriorityCustomer의 복사함수는 선언된 멤버들을 전부 복사하고 있는 것 같다.&lt;/li&gt;
&lt;li&gt;그러나... Customer의 멤버함수는.. 복사가 되고 있지 않다!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;해결 방안&lt;/h2&gt;
&lt;pre id=&quot;code_1731935509837&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PriorityCustomer::PriorityCustomer(const PriorityCustomer&amp;amp; rhs)
    :Customer(rhs), priority(rhs.priority)	// 기본 클래스의 복사 생성자 호출
{
    logCall(&quot;PriorityCustomer Copy Constructor&quot;);
}

PriorityCustomer&amp;amp; PriorityCustomer::operator= (const PriorityCustomer&amp;amp; rhs) {
    logCall(&quot;PriorityCustomer Copy Assignment Operator&quot;);
    Customer::operator=(rhs);	// 기본 클래스 부분을 대입
    priority = rhs.priority;
    return *this;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파생 클래스의 복사 함수에서 기본 클래스의 복사 함수를 호출하게 만들자.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복사 생성자의 경우, 초기화 리스트에서 기본 클래스의 복사 생성자를 호출한다.&lt;/li&gt;
&lt;li&gt;복사 대입 연산자의 경우, 함수 내부에서 기본 클래스의 복사 대입 연산자를 호출한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;따라서, 객체의 복사 함수를 구현할 때는 다음 두가지를 꼭 확인한다.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 클래스의 데이터 멤버를 &lt;b&gt;모두 복사&lt;/b&gt;한다.&lt;/li&gt;
&lt;li&gt;이 클래스가 상속한 &lt;b&gt;기본 클래스의 복사 함수&lt;/b&gt;를 호출한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;그런데.. 복사 생성자랑 복사 대입 연산자는 내용이 비슷할텐데, 한쪽에서 다른 쪽을 호출하는 방식으로 쓰면 코드 중복도 피하고 좋지 않나?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;안됨.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;복사 생성자&lt;/b&gt;: 새로운 객체를 생성하고 다른 객체의 내용을 복사하여 초기화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;복사 대입 연산자&lt;/b&gt;: 이미 생성된(초기화 완료된) 객체에 다른 객체의 내용을 복사&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;복사 대입 연산자에서 복사 생성자를 호출하는 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미 객체가 생성되어 있는 상황에서 또다시 새로운 객체를 생성한다고? 말 안됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;복사 생성자에서 복사 대입 연산자를 호출하는 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대입 연산자는 이미 초기화가 끝난 객체에 값을 넣어주는 거임. 아직 초기화도 안 된 객체에 대해 대입이라고? 말 안됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Effective/Effective C++</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/379</guid>
      <comments>https://grace7040.tistory.com/379#entry379comment</comments>
      <pubDate>Mon, 18 Nov 2024 22:21:22 +0900</pubDate>
    </item>
    <item>
      <title>[EC++] 11. operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자</title>
      <link>https://grace7040.tistory.com/378</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;자기대입이란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 객체가 자기 자신에 대해 대입 연산자를 적용하는 것을 의미한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731832334297&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Widget {...};
widget w;
...
w = w;	// 자기대입&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;얼핏 보면 딱히 사용될 일이 없어보인다. 그러나, 다음과 같은 상황은 어떨까?&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731832431044&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;a[i] = a[j];&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 구문은 i == j일 때, 자기대입문이 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731832481445&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;*px = *py;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 구문은 px와 py가 가리키는 대상이 같을 때, 자기대입문이 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자기대입이 생기는 이유는?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복참조(aliasing) 시에 자기 대입이 발생할 가능성이 크다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 곳에서 하나의 객체를 참조하는 상태&lt;/li&gt;
&lt;li&gt;같은 타입으로 만들어진 객체 여러 개를 참조자 혹은 포인터로 물어 놓고 동작하는 코드를 작성할 때는, 같은 객체가 사용될 가능성을 고려하는 것이 바람직하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자기대입 시 생길수 있는 문제&lt;/h2&gt;
&lt;pre id=&quot;code_1731833567131&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Bitmap { ... };
class Widget {
    ...
private:
    Bitmap* pb;		// 동적 할당한 객체를 가리키는 포인터
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Widget 클래스의 멤버 중, 동적 할당한 비트맵 객체를 가리키는 포인터가 있다고 하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731833714843&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Widget&amp;amp; Widget::operator= (const Widget&amp;amp; rhs) {
    delete pb;			// 현재 비트맵 삭제
    pb = new Bitmap(*rhs.pb);	// rhs의 비트맵을 사용하기로 함
    return *this;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위와 같이 대입 연산자를 구성하면 좌변 객체의 비트맵을 우변 객체의 비트맵으로 바꿔줄 수 있다.&lt;/li&gt;
&lt;li&gt;그러나, 만약 두 객체가 같은 객체였다면?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;삭제된 비트맵 객체를 참조하게 된다...!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결 방안 1. 일치성 검사&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 간단한 해결책으로, 대입 연산자 첫머리에서 &lt;i&gt;두 객체가 같은지 검사&lt;/i&gt;하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731833901678&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Widget&amp;amp; Widget::operator= (const Widget&amp;amp; rhs) {
    if (this == &amp;amp;rhs) return *this;		// 자기대입인지 검사

    delete pb;
    pb = new Bitmap(*rhs.pb);
    return *this;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그러나 여전히 문제가 있는데, 예외에 안전하지 않다는 것이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약, delete pb;를 마치고 pb에 새로운 비트맵을 할당해주려고 하는데, 이 new 과정에서 메모리 부족 등의 예외가 터지게 된다면?&lt;/li&gt;
&lt;li&gt;결국 좌변 객체는 삭제된 비트맵을 가리키는 포인터를 그대로 갖게 된다...!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결 방안 2. 순서를 잘 바꿔보자&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원래 pb를 기억해두고 삭제할 새 포인터를 만든다.&lt;/li&gt;
&lt;li&gt;pb가 rhs의 비트맵을 가리키게 만든다.&lt;/li&gt;
&lt;li&gt;아까 만든 새 포인터로 원래 pb를 삭제한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731834205162&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Widget&amp;amp; Widget::operator= (const Widget&amp;amp; rhs) {
    Bitmap* pOrig = pb;
    pb = new Bitmap(*rhs.pb);
    delete pOrig;
    return *this;
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 코드는 예외에 안전하며, 자기대입에도 안전하다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;new 부분에서 예외가 터지면 delete 구문이 실행되지 않으므로, pb는 그대로 원본 비트맵을 가리키는 상태이다.&lt;/li&gt;
&lt;li&gt;자기 대입문일지라도, pb가 rhs의 비트맵의 사본을 만들어 가리키는 시점에 rhs의 비트맵이 삭제되었을 가능성이 없으므로 안전하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이 코드는 제법 비효율적으로 보일 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자기대입이 그렇게 자주 일어나는 것도 아닌데, 할 때마다 저런 과정을 거쳐야 하나!!! 생각할 수도 있다.&lt;/li&gt;
&lt;li&gt;그래서 걍 일치성 검사를 하고싶어질 수도 있다.&lt;/li&gt;
&lt;li&gt;그런데 일치성 검사 하는 것도 공짜는 아니다.&lt;/li&gt;
&lt;li&gt;일치성 검사를 하면 분기를 만들게 되므로 실행 시간 속력이 줄어들 수도 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결 방안 3. copy and swap&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해결 방안 2와 비슷한 다른 방안이 하나 더 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731835444173&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Widget {
    ...
    void swap(Widget&amp;amp; rhs);
};

Widget&amp;amp; Widget::operator= (const Widget&amp;amp; rhs) {
    Widget temp(rhs);
    swap(temp);
    return *this;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문장 실행 순서를 의도적으로 조작하는 대신, 사본 객체 하나를 만들어서 둘을 바꿔주는 것이다. (복사 생성자 사용)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이를 pass by value로 구현할 수도 있는데, 다음과 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731836192477&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Widget&amp;amp; Widget::operator= (Widget rhs) {
    swap(rhs);
    return *this;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 경우 자동으로 사본으로 넘어오므로 복사 생성자를 사용하지 않아도 된다.&lt;/li&gt;
&lt;li&gt;객체를 복사하는 코드가 함수 본문으로부터 매개변수의 생성자로 옮겨졌기 때문에, 컴파일러가 더 효율적인 코드를 생성할 수 있는 여지가 생긴다고 한다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 대목에서 어떤 최적화가 일어날 수 있는 건지는 잘 모르겠다. &lt;br /&gt;복사 생성자 호출 과정에서 임시 객체가 생기나 했는데 그건 또 아닌 것 같다. 흠...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그러나 아무래도 객체를 값으로 전달하는 것은 좀..그렇고, &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;코드의 명확성이 좀 떨어지긴 한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Effective/Effective C++</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/378</guid>
      <comments>https://grace7040.tistory.com/378#entry378comment</comments>
      <pubDate>Sun, 17 Nov 2024 18:49:15 +0900</pubDate>
    </item>
    <item>
      <title>[EC++] 10. 대입 연산자는 *this의 참조자를 반환하게 하자</title>
      <link>https://grace7040.tistory.com/377</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;C++ 대입 연산은 여러 개가 사슬처럼 엮일 수 있다.&lt;/h2&gt;
&lt;pre id=&quot;code_1731831860403&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int x, y, z;
x = y = z = 15;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;z에 15가 대입되고, 갱신된 z가 y에 대입되고, 갱신된 y가 x에 대입되는 형태이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이것이 가능한 이유는?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대입 연산자가 &lt;i&gt;좌변 인자(자기 자신)에 대한 참조자를 반환&lt;/i&gt;하도록 구현되어 있기 때문이다.&lt;/li&gt;
&lt;li&gt;이는 일종의 관례이며, 우리가 커스텀 클래스를 만들 때도 대입 연산자는 이런 식으로 구현하는 것이 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731832060566&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Widget {
public:
    ...
    Widget&amp;amp; operator= (const Widget&amp;amp; rhs) {
    	...
        return *this;
    }
    
    Widget&amp;amp; operator+= (const Widget&amp;amp; rhs) {
    	...
        return *this;
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;= 뿐만 아니라 +=, -=, *= 등에도 동일한 규약이 적용된다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Effective/Effective C++</category>
      <author>seeyoun</author>
      <guid isPermaLink="true">https://grace7040.tistory.com/377</guid>
      <comments>https://grace7040.tistory.com/377#entry377comment</comments>
      <pubDate>Sun, 17 Nov 2024 17:29:44 +0900</pubDate>
    </item>
  </channel>
</rss>