..

C++ Core Guideline

아래 가이드라인들은 항상 정답이 아니므로 비판적으로 사용하길 바랍니다

"생각을 코드로 직접 표현하라",
"ISO 표준 c++로 코드를 작성하라",
"의도를 표현하라",
"이상적으로, 프로그램은 정적 형식 안정성을 갖추어야 한다",
"실행 시점 점검보다는 컴파일 시점 점검을 선호하라",  
"컴파일 시점에서 점검할 수 없는 것은 실행 시점에서 점검할 수 있어야 한다",
"실행 시점 오류는 일찍 잡아라",
"자원이 새지 않게 하라",
"시간이나 공간을 낭비하지 말라",
"변경 가능 데이터보다 변경 불가 데이터를 선호하라",
"지저분한 프로그램 요소들을 코드 전체에 흩어놓지 말고 한 곳에 캡슐화하라",
"지원 도구들을 적절히 활용하라",
"지원 라이브러리를 적절히 활용하라",
"비const 전역 변수를 피하라",
"단일체(싱글턴)를 피하라",
"배열을 단일 포인터로 전달하지 말라",
"안정적인 라이브러리 ABI를 원한다면 PImpl 관용구를 고려하라",
"컴파일 시점에서 평가될 수 있는 함수는 constexpr로 선언하라",
"함수가 예외를 던지지 않는다면 noexcept로 선언하라",
"순수 함수를 선호하라",
"단순하고 통상적인 방식의 정보 전달을 선호하라",
"입력 매개변수는 복사 비용이 낮은 형식이면 값으로, 그 밖의 형식이면 참조로 전달하라",
"전달 매개변수는 TP&&로 받고 std::forward로만 전달하라",
"입출력 매개변수는 비const 참조로 전달하라",
"함수가 어떤 값을 출력할 때는 출력 매개변수보다는 반환값을 선호하라",
"여러 개의 출력값을 돌려줄 때는 구조체나 튜플을 돌려주는 방식을 선호하라",

"위치를 나타내려면(그리고 그럴 때만) T*를 반환하라",
"복사가 바람직하지 않으며 아무 객체도 돌려주지 않음이 필요하다면 T&를 반환하라",
"T&&를 반환하지 마라",
"std::move(지역객체)를 반환하지 마라",
"main()의 반환 형식은 int이다",
"람다는 보통의 함수로는 할 수 없는 일(지역 변수 갈무리, 지역 함수 정의)에 사용하라",
"람다 안에서 지역적으로 쓰이는(알고리즘으로 전달하는 것도 포함해서) 데이터는 가능한 한 참조로 갈무리하라",
"지역적으로 사용할 것이 아닌(반환하거나, 힙에 저장하거나, 다른 스레드로 전달하는 등) 데이터는 참조로 갈무리 하지 않는 것이 좋다",
"선택할 수 있다면 중복적재보다는 기본 인수를 선호하라",
"va_arg 인수는 사용하지 말라",
"관련된 데이터를 구조체(structure:struct 또는 class)로 조직화하라",
"불변식이 있는 클래스에는 class를 적용하라. 데이터 멤버들이 독립접으로 변할 수 있으면 struct를 적용하라",
"인터페이스와 구현의 구분을 클래스를 이용해서 표현하라",
"클래스의 표현에 직접 접근해야 하는 함수만 멤버 함수로 만들라",
"클래스의 보조 함수들은 그 클래스와 같은 이름공간에 배치하라",
"하나의 문장에서 class와 enum을 정의하고 즉시 해당 형식의 변수를 선언하지 말라",
"public이 아닌 멤버가 있다면 struct 대신 class를 사용하라",
"멤버들을 최소한으로 노출하라",
"클래스 위계구조보다 구체 형식들을 선호하라",
"구체 형식은 정규 형식으로 작성하라",
"가능하면 기본 연산은 아예 정의하지 말라",
"기본 연산을 하나라도 정의하거나 =delete로 삭제했다면, 다른 모든 기본 연산도 정의하거나 삭제하라",
"기본 연산들의 일관성을 유지하라",
"생성자는 완전하게 초기화된 객체를 생성해야 한다",
"생성자에서 유효한 객체를 생성할 수 없으면 예외를 던져라",
"복사 가능(값 형식) 클래스에는 반드시 기본 생성자가 있어야 한다",
"데이터 멤버들을 초기화하기만 하는 기본 생성자는 정의하지 말고, 대신 멤버 초기화 구문을 사용하라",

"기본적으로, 단일 인수 생성자는 explicit로 선언하라",
"멤버 변수들을 멤버 선언 순으로 정의하고 초기화하라",
"생성자에서 멤버를 상수로 초기화할 때 멤버 초기화 구문보다는 클래스 안 초기화 구문을 선호하라",
"생성자 안의 배정보다는 멤버 초기화 구문을 선호하라",
"한 클래스의 모든 생성자에 공통인 작업들은 위임 생성자로 표현하라",
"더 이상의 명시적 초기화가 필요하지 않은 파생 클래스에 기반 클래스의 생성자를 도입할 때는 상속 생성자를 사용하라",
"다형적 클래스는 복사를 금지해야 한다",
"객체가 파괴될 때 어떤 작업을 명시적으로 수행해야 하는 클래스에는 소멸자를 정의하라",
"클래스가 획득한 모든 자원은 반드시 클래스의 소멸자에서 해제해야 한다",
"클래스에 원시 포인터(T*)나 참조(T&) 멤버가 있으면, 그 멤버가 자원을 소유하는지 따져 봐야 한다",
"클래스에 다른 객체를 소유하는 포인터 멤버가 있으면 소멸자를 정의하라",
"기반 클래스의 소멸자는 public과 vitual의 조합이거나 protected와 비 vitual의 조합이어야 한다",
"만일 기본 의미론이 적용됨을 명시적으로 밝혀야 한다면 =default를 사용하라",
"기본 행동 방식을 비활성화하려면 =delete를 사용하라 (다른 방법 대신)",
"생성자와 소멸자에서는 가상 함수를 호출하지 말라",
"==를 피연산자 형식들에 대칭으로 작성하고 noexcept로 선언하라",
"기반 클래스들에 대한 ==를 조심하라",
"클래스 위계구조는 위계적인 구조가 자연스러운 개념들을 표현하는 용도로(만) 사용하라",
"인터페이스로 사용할 기반 클래스는 추상 클래스로 만들어라",
"인터페이스와 구현을 완전하게 분리해야 할 때는 추상 클래스를 인터페이스로 사용하라",
"보통의 경우 추상 클래스에는 생성자가 필요 없다",
"가상 함수에는 virtual, override, final 중 딱 하나만 지정해야 한다",
"다형적 클래스에 깊은 복사를 적용할 때는 복사 생성/배정보다 가상 clone 함수를 선호하라",
"이유 없이 함수를 virtual로 만들지는 말라",
"자명한 조회 함수와 설정 함수를 피하라",
"protected 데이터를 피하라",

"모든 비const 데이터 멤버의 접근 수준을 동일하게 유지하라",
"클래스 위계구조를 설계할 때 구현 상속과 인터페이스 상속을 구분하라",
"서로 구별되는 여러 인터페이스는 다중 상속을 이용해서 표현하라",
"파생 클래스와 그 기반 클래스들을 위한 중복적재 집합을 작성할 때 using 선언을 사용하라",
"가상 함수와 재정의 함수의 기본 인수들이 서로 달라서는 안 된다",
"클래스 위계구조 안에서의 이동이 불가피하면 dynamic_cast를 사용하라",
"요구된 클래스를 찾지 못했을 때 오류가 발생해야 한다면 dynamic_cast를 참조 형식에 적용하라",
"요구된 클래스를 찾지 못한 것을 유효한 선택지로 간주할 수 있다면 dynamic_cast를 포인터 형식에 적용하라",
"파생 클래스 객체들의 배열을 가리키는 포인터를 기반 클래스 객체를 가르키는 포인터에 배정하면 절대로 안된다",
"연산자는 통상적인 의미의 연산을 수행하는 데 사용하라",
"대칭적인 연산자에는 비멤버 함수를 사용하라",
"암묵적인 변환 연산자를 피하라",
"대체로 동등한 연산들을 중복적재하라",
"중복적재된 연산자는 해당 피연산자의 이름공간 안에서 정의하라",
"union은 메모리를 절약하는 데 사용하라",
"헐벗은 union을 피하라",
"태그된 공용체는 익명 union을 이용해서 구현하라",
"매크로보다 열거형을 선호하라",
"열거형은 연관된, 이름 붙은 상수들의 집합을 표현하는 데 사용하라",
"평범한 enum보다 enum class를 선호하라",
"열거자에 ALL_CAPS 형태의 이름을 사용하지 말라",
"이름 없는 열거형을 피하라",
"열거형의 바탕 형식은 꼭 필요할 때만 명시하라",
"열거자의 값은 꼭 필요할 때만 명시하라",
"자원 핸들과 RAII를 이용해서 자원을 자동으로 관리하라",
"원시 포인터(T*)는 비소유(non-owning)이다",
"원시 참조(T&)는 비소유이다",
"범위 있는 객체를 선호하라",
"불필요하게 힙을 할당하지 말라",
"malloc()과 free()를 피하라",

"new와 delete의 명시적인 호출을 피하라",
"명시적인 자원 할당의 결과를 즉시 관리자 객체에 전달하라",
"하나의 표현식 문장에서 명시적인 자원 할당은 많아야 한 번만 수행하라",
"소유권은 unique_ptr나 shared_ptr를 이용해서 표현하라",
"소유권을 공유할 필요가 없다면 shared_ptr보다 unique_ptr를 선호하라",
"shared_ptr 객체는 make_shared()로 생성하라",
"unique_ptr 객체는 make_unique()로 생성하라",
"shared_ptr들의 순환 참조 관계를 깨려면 std::weak_ptr를 사용하라",
"수명 의미론을 명시적으로 나타내고자 할 때만 스마트 포인터를 매개변수로 사용하라",
"재명명된 스마트 포인터로 얻은 포인터나 참조를 전달하지 마라",
"표준 라이브러리를 다른 라이브러리나 손으로 직접 짠 코드보다 선호하라",
"언어의 기능을 직접 사용하기보다는 적절한 추상을 선호하라",
"범위를 작게 유지하라",
"for 문의 초기화 구문과 조건문 안에서 이름을 선언해서 범위를 최소화하라",
"흔하고 지역 범위에 있는 이름은 짧게, 흔하지 않고 지역 범위가 아닌 이름은 길게 지어라",
"비슷하게 보이는 이름들을 피하라",
"ALL_CAPS 이름을 피하라",
"하나의 선언문에서는 하나의 이름만 선언하라",
"auto를 이용해서 형식 이름의 불필요한 중복을 피하라",
"내포된 범위들에서 이름을 재사용하지 말라",
"객체를 항상 초기화하라",
"필요하기도 전에 변수(또는 상수)를 도입하지는 말라",
"초기화할 값을 갖추기 전에 변수를 선언하지 말라",
"{} 초기화 구문을 선호하라",
"하나의 변수를 서로 무관한 두 가지 용도로 사용하지 말라",
"복잡한 초기화에는, 특히 const 변수의 복잡한 초기화에는 람다를 사용하라",
"복잡한 표현식은 피하라",
"연산자 우선순위에 자신이 없으면 괄호를 사용하라",
"포인터는 간단하고 직관적으로만 사용하라",
"마법의 상수를 피하고 기호 상수를 사용하라",
"색인 범위 점검이 필요한 상황을 피하라",
"0이나 NULL 대신 nullptr를 사용하라",

"배열은 delete[]로 삭제하고 배열이 아닌 객체는 delete로 삭제하라",
"유효하지 않은 포인터를 역참조하지 말라",
"평가 순서가 정의되지 않는 표현식을 피하라",
"함수 인수들의 평가 순서에 의존하지 말라",
"형변환을 피하라",
"형변환이 꼭 필요하다면 명명된 형변환을 사용하라",
"const를 강제로 제거하지 말라",
"switch 문에서 암묵적인 실행 지속에 의존하지 말라",
"공통의 사레들은(그리고 그런 사례들만) default로 처리하라",
"부호 있는 산술과 부호 없는 산술을 섞지 말라",
"비트 조작에는 부호 없는 형식을 사용하라",
"산술에는 부호 있는 형식을 사용하라",
"unsigned를 이용해서 음수를 피하려 들지 말라",
"위넘침(overflow)을 허용하지 말라",
"아래넘침(underflow)을 허용하지 말라",
"0으로 나누기를 허용하지 말라",
"최적화가 가능하도록 설계하라",
"정적 형식 시스템에 의존하라",
"계산을 실행 시점에서 컴파일 시점으로 이동하라",
"메모리에 예측 가능한 방식으로 접근하라",
"여러분의 코드가 다중 스레드 프로그램의 일부로 실행될 것이라고 가정하라",
"데이터 경쟁을 피하라",
"쓰기 가능 데이터의 명시적인 공유를 최소화하라",
"스레드가 아니라 작업의 관점에서 사고하라",
"volatile을 동기화에 사용하지는 말라",
"가능하면 항상 적절한 도구를 이용해서 동시적 코드의 유효성을 검증하라",
"항상 RAII를 적용하고, lock()/unlock()은 절대로 직접 사용하지 말라",
"여러 개의 뮤텍스를 획득할 때는 std::lock()이나 std::scoped_lock을 사용하라",
"자물쇠를 잠근 상태에서 절대로 미지의 코드(이를테면 콜백 함수)를 호출하지 말라",
"주 스레드에 합류하는(joining) thread를 일종의 범위 있는 컨테이너로 간주하라",
"thread를 전역 컨테이너로 간주하라",

"std::thread보다 std::jthread를 선호하라",
"스레드를 분리하지(detach()) 말라",
"조건 없이 대기하지(wait) 말라",
"스레드에서 스레드로 작은 데이터를 넘겨줄 때는 참조나 포인터 대신 값으로 전달하라",
"서로 무관한 thread들이 소유권을 공유할 때는 shared_ptr를 사용하라",
"문맥 전환을 최소화하라",
"스레드의 생성과 파괴를 최소화하라",
"임계 영역에서 소비하는 시간을 최소화하라",
"lock_guards와 unique_locks에 이름을 붙이는 것을 잊지 말라",
"절대적으로 필요하지 않은 한 무잠금 프로그래밍을 사용하지 말라",
"여러분의 하드웨어/컴파일러 조합을 신뢰하지 말라",
"문헌들을 세심하게 공부하라",
"예외는 오류 처리에만 사용하라",
"목적에 맞게 설계한 사용자 정의 형식을 예외로 사용하라(내장 형식들 말고)",
"위계구조에 속한 예외들은 참조로 잡아라",
"객체를 직접 소유한 상황에서는 절대로 예외를 던지지 말라",
"예외 명세는 사용하지 말라",
"catch 절들을 적절한 순서로 배치하라",
"기본적으로 객체를 변경 불가(immutable)로 만들어라",
"기본적으로 멤버 함수에 const를 적용하라",
"기본적으로 포인터와 참조는 const로 전달하라",
"생성 이후 값이 변하지 않는 객체를 정의할 때 const를 사용하라",
"컴파일 시점에서 계산할 수 있는 값에는 constexpr를 적용하라",
"템플릿을 코드의 추상 수준을 높이는 데 사용하라",
"다수의 인수 형식들에 적용할 알고리즘을 표현할 때 템플릿을 사용하라",
"컨테이너와 구간을 표현할 때 템플릿을 사용하라",
"연산을 알고리즘에 전달할 때 함수 객체를 사용하라",
"표기를 간단하게 만들고 구현 세부사항을 숨기기 위해 템플릿 명칭을 사용하라",
"별칭을 정의할 때 typedef보다 using을 선호하라",
"클래스 인수 형식을 연역할 때 함수 템플릿을 사용하라(가능한 경우에)",
"템플릿 인수의 요구조건을 적어도 Regular 또는 SemiRegular로 저장하라",
"가시성이 높지만 제약이 없는 흔한 이름의 템플릿을 피하라",

"컴파일러가 콘셉츠를 지원하지 않는다면 enable_if로 흉내 내라",
"템플릿의 문맥 의존성을 참고하라",
"멤버들을 과도하게 매개변수화하지 말라",
"비의존적 클래스 템플릿 멤버들을 비템플릿 기반 클래스에 배치하라",
"클래스 위계구조를 어수룩하게 템플릿하지 말라",
"멤버 함수 템플릿을 virtual로 선언하지 말라",
"재사용할 수 있는 연산에는 이름을 붙여라",
"한 곳에서만 사용할 간단한 함수 객체가 필요할 때는 익명 람다를 사용하라",
"무심코 비일반적인 코드를 작성하지 말라",
"함수 템플릿은 특수화하지 말라",
"C보다 C++를 선호하라",
"C를 꼭 사용해야 한다면 C와 C++의 공통 부분집합을 사용하고, C 코드를 C++로서 컴파일하라",
"C 인터페이스를 꼭 사용해야 한다면, 그런 인터페이스를 사용하는 호출 코드를 C++로 작성하라",
"프로젝트가 다른 어떤 관례를 따르지 않는 한, 코드 파일의 확장자로는 .cpp를 사용하고 인터페이스 파일의 확장자로는 .h를 사용하라",
".h 파일에 객체 정의나 비인라인 함수 정의를 담으면 안 된다",
".cpp 파일은 자신의 인터페이스를 정의하는 .h 파일을 포함해야 한다",
"모든 .h 파일에 #include 가드를 사용하라",
"소스 파일들 사이의 순환 의존관계를 피하라",
"간접적으로 #include된 이름들의 의존관계를 피하라",
"헤더 파일은 자기 완결적이어야 한다",
"using namespace 지시문을 전이(transition)를 위해서, 기반 라이브러리(std)를 위해서, 또는 지역 범위 안에서 사용하라",
"헤더 파일의 전역 범위에서는 using namespace를 사용하지 말라",
"namespace들을 논리적인 구조를 표현하는 데 사용하라",
"헤더에서 이름 없는(익명) 이름공간을 사용하지 말라",
"내부에서만 사용할, 외부로 내보내지 않을 개체들은 모두 이름 없는 이름공간 안에 포함시켜라",
"C 배열보다 STL array나 vector를 선호하라",
"다른 컨테이너를 사용할 특별한 이유가 없는 한 기본적으로 STL의 vector를 선호하라",
"경계 오류를 피하라",

"문자 순차열을 소유하려면 std::string을 사용하라",
"문자 순차열을 참조하려면 std::string_view를 사용하라",
"문자 하나를 참조하려면 char*를 사용하라",
"반드시 문자를 표현하는 것은 아닌 바이트 값을 참조할 때는 std::byte를 사용하라",
"표준 라이브러리 문자열로 취급할 문자열 리터럴에는 접미사 s를 사용하라",
"문자 수준 입력은 꼭 필요할 때만 사용하라",
"읽기 작업 시에는 입력이 잘못된 형태일 수 있음을 항상 고려하라",
"입출력 작업에는 iostream 라이브러리를 선호하라",
"printf류 함수들을 사용하지 않는다면 ios_base::sync_with_stdio(false)를 호출하라",
"endl을 피하라",
"안정된 코드와 덜 안정된 코드를 분리하라",
"잠재적으로 재사용 가능한 부품들을 라이브러리로 표현하라",
"라이브러리들 사이에 순환 의존관계가 없어야 한다",
"모든 선언을 함수의 최상단에 두려고 고집하지 말라",
"함수에 반환문을 하나만 두려고 고집하지 말라",
"예외를 꺼리지 말라",
"클래스 선언을 개별 소스 파일에 두려고 고집하지 말라",
"2단계 초기화를 사용하지 말라",
"마무리 작업들을 제일 끝에 몰아넣고 goto exit로 넘어가는 방식으로 함수를 작성하지 말라",
"모든 데이터 멤버를 protected로 만들지는 말라"

출처 : 쉽게 설명한 C++ 핵심 가이드라인