[C++] 알고 있으면 좋은 C++ 개발 지식 & 습관

Date:     Updated:

카테고리:

태그:

이 글은 C++을 공부하면서 알게된 지식과 습관을 정리해둔 글입니다

참고사항

  • 이것은 제가 공부하면서 알게된 지식과 습관을 정리해둔것으로 코딩 표준은 아닐수 있으니 그점 유의하면서 봐주세요

함수를 만들 때 함수 시그니처만 보고 어떤 기능을 할지 알수 있어야 한다

  • 주석도 안보는 사람들이 있을 수 있기 때문에 함수 시그니처를 명백하게 만들어야 한다

new를 해주었으면 delete도 필수

  • 메모리 누수(Memory Leak)를 줄이는 좋은 습관

관련 글 보러가기

모든 소멸자에 언제나 virtual 키워드를 붙일 것

  • 만약 클래스를 상속받고 delete 해주었을때 메모리 누수(Memory Leak)가 생길수도 있기 때문

관련 글 보러가기

되도록 const를 사용할 수 있는 변수에는 const를 사용하자

  • 의도치 않은 실수를 막을 수 있다

관련 글 보러가기

const & 를 사용해서 불필요한 개체의 사본이 생기는 것을 방지하자

  • 멤버 변수가 바뀌는 것도 방지

관련 글 보러가기

인터페이스를 만들면 가상 소멸자도 추가할 것

  • 인터페이스를 상속 받는 클래스의 소멸자가 호출 안될수도 있기 때문에

관련 글 보러가기

캐스팅 규칙

  1. 기본적으로 static_cast를 쓸 것
    • reinterpret_cast<Cat> 대신 static_cast<Cat>
      • 만약 Cat이 Animal이 아니라면 컴파일러가 에러를 뱉음
  2. reinterpret_cast를 쓸 것
    • 포인터와 비포인터 사이의 변환
    • 서로 연관이 없는 포인터 사이의 변환은 그 데이터형이 맞다고 정말 확인할 때만 할 것
  3. 내가 변경권한이 없는 외부 라이브러리를 호출할 때만 const_cast를 쓸 것

관련 글 보러가기

간단한 함수를 만드는 경우 inline으로 만들자

  • 함수 호출에 필요한 오버헤드를 줄일 수 있다
  • 특히 getter나 setter

관련 글 보러가기

적절한 예외 처리 전략

  1. 유효성 검사/예외는 오직 경계에서만
    • 밖에서 오는 데이터를 제어할 수 없기 때문
    • 예) 외부에서 들어오는 웹 요청, 파일 읽기/쓰기, 외부 라이브러리
  2. 일단 시스템에 들어온 데이터는 다 올바르다고 간주할 것
    • assert를 사용하여 개발 중 문제를 잡아내고 고칠것
  3. 예외 상황이 발생할 때는 NULL을 능동적으로 사용할 것
    • 하지만 기본적으로 함수가 NULL을 반환하거나 받는 일은 없어야 함
    • 코딩 표준 : 만약 NULL을 반환하거나 받는다면 함수의 이름을 잘 지을 것

관련 글 보러가기

static_assert와 assert를 많이 사용하자

  • static_assert와 assert를 많이 사용하면 디버깅 중에 버그를 빨리 잡을 수 있다

관련 글 보러가기

빈번한 메모리 재할당은 메모리 단편화를 초래한다

  • 메모리 단편화는 엄청난 문제가 될 수 있음. 특히 가상 메모리를 지원하지 않는 플랫폼에서 프로그램을 실행할 때
  • 메모리 단편화 때문에 애플리케이션이 뻗어 버릴 수 있음
    • 즉, 총 여유 공간은 충분하나 충분히 큰 연속되는 메모리가 없는 경우
  • 디버깅 및 고치는 게 쉽지 않음

관련 글 보러가기

auto로 사용할 땐 가독성을 신경써라

  • 명시적이어야 함
    1. auto보다 실제 자료형 사용을 권장
    2. 예외: 템플릿 매개변수와 반복자에는 auto 사용
    3. auto보다 auto*를 사용
    4. auto&보다 const auto&를 사용
  • 전부 가독성과 관련된 것

관련 글 보러가기

default와 delete를 사용해 기본 생성자, 연산자 및 소멸자를 더 분명하게 표시하자

  • 컴파일러가 코드를 생성하는 암시적 방식에 기댈 필요가 없음
  • 올바른 에러 메시지도 나옴

관련 글 보러가기

포인터에는 언제나 nullptr를 쓰자

  • 더 이상 NULL을 쓸 필요가 없음
  • 그리고 더 명시적임

가독성 향상을 위해서 낡은 기존 자료형보다 고정 폭 정수형을 사용하자

int32_t score = 64;

순수 가상 소멸자의 정의를 두지 않으면 안된다

  • 소멸자가 동작하는 순서는 상속 계통 구조에서 가장 말단에 있는 파생 클래스의 소멸자가 호출되는 것을 시작으로, 기본 클래스 쪽으로 거쳐 올라가면서 각 기본 클래스의 소멸자가 하나씩 호출됩니다
  • 컴파일러는 ~AWOV의 호출 코드를 만들기 위해 파생 클래스의 소멸자를 사용할 것이므로, 잊지 말고 이 함수의 본문을 준비해 두어야 한다
  • 만약 이 부분을 잊으면 링커 에러를 보게 된다

객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자

  • 생성자는 파생 클래스 객체가 생성될 때 그 객체의 기본 클래스 부분이 파생 클래스 부분보다 먼저 호출된다
  • 만약 기본 클래스 생성자에서 logTransaction 함수를 호출하면 파생 클래스의 logTransaction 함수가 아닌 기본 클래스의 logTransaction 함수가 호출되게 된다
  • 기본 클래스의 생성자가 호출될 동안에는, 가상 함수는 절대로 파생 클래스 쪽으로 내려가지 않는다
  • 그 대신, 객체 자신이 기본 클래스 타입인 것처럼 동작한다
  • 기본 클래스 생성자가 돌아가고 있을 시점에 파생 클래스 데이터 멤버는 아직 초기화된 상태가 아니라는 것이 핵심이다
  • 아직 초기화되지 않는 데이터 멤버를 건드리면 ‘미정의 동작’이 발생될 수 있다
  • 이렇듯 어떤 객체의 초기화되지 않은 영역을 건드린다는 것은 치명적인 위험을 내포하기 때문에, C++는 이런 실수조차 하지 못하도록 막은 것이다
  • 파생 클래스 객체의 기본 클래스 부분이 생성되는 동안은, 그 객체의 타입은 바로 기본 클래스이다
  • 호출되는 가상 함수는 모두 기본 클래스의 것으로 결정될 뿐만 아니라, 런타임 타입 정보를 사용하는 언어 요소(dynamic_cast나 typeid 같은 것)를 사용한다고 해도 이 순간엔 모두 기본 클래스 타입의 객체로 취급된다
  • 객체가 소멸될 때도 똑같이 생각하면 된다
  • 해결법은 비가상 멤버 함수로 바꾸는 것이다


💻 열심히 공부해서 작성 중이니 오류나 틀린 부분이 있을 경우 
  언제든지 댓글 혹은 메일로 알려주시면 감사하겠습니다! 😸

맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

첫 번째 글입니다 가장 최근 글입니다

댓글 남기기