반응형
함수 정의 규칙:
- F.1: 의미있는 동작들을 "묶어서" 함수로 만들고 신중하게 이름을 지어라
- F.2: 함수는 하나의 논리적 동작만 수행해야 한다
- F.3: 함수는 간결하고 단순하게 유지하라
- F.4: 함수가 컴파일 시간에 평가되어야 한다면 constexpr로 선언하라
- F.5: 함수가 매우 짧고 수행시간이 중요하다면 inline으로 선언하라
- F.6: 함수가 예외를 던지지 않는다면 noexcept로 선언하라
- F.7: 보편성을 고려한다면, 스마트 포인터 대신에 T*나 T& 타입의 인자를 사용하라
- F.8: 순수 함수를 선호하라
- F.9: 사용되지 않는 인자는 이름이 없어야 한다
매개변수 전달 표현(parameter passing expression) 규칙:
- F.15: 정보를 전달 할 때 단순하고 관습적인 방법을 선호하라
- F.16: "입력(in)" 매개변수는 복사 비용이 적게 드는 타입의 경우 값으로 전달하고, 그 외에는 상수 참조형으로 전달하라
- F.17: "입출력(in-out)" 매개변수는 비상수 참조형으로 전달하라
- F.18: "넘겨주는(will-move-from)" 매개변수는 X&&타입과 std::move로 전달하라
- F.19: "전달(forward)" 매개변수는 TP&&타입과 std::forward로만 전달하라
- F.20: "출력(out)"에는 매개변수보다는 값을 반환하는 방법을 선호하라
- F.21: "출력"값 여러 개를 반환할 때는 튜플이나 구조체를 선호하라
매개변수 전달 의미구조(parameter passing semantic) 규칙:
- F.22: T* 혹은 owner<T*>를 단일 개체를 지정하기 위해 사용하라
- F.23: "null"이 허용되지 않는다면 not_null<T>를 사용해 표시하라
- F.24: 범위를 지정할 때는 span<T>혹은 span_p<T>를 사용하라
- F.25: C 스타일 문자열에는 zstring 혹은 not_null<zstring>을 사용하라
- F.26: 포인터가 필요한 곳에 소유권을 전달할 때는 unique_ptr<T>를 사용하라
- F.27: 소유권을 공유할 때는 shared_ptr<T>를 사용하라
- F.60: "인자가 없을 경우"를 허용한다면 T&보다는 T*를 선호하라
값 반환 의미구조 규칙:
- F.42: 위치를 나타내는 경우에만 T*를 반환하라
- F.43: 절대로 (직접적이든 간접적이든) 지역 개체의 포인터나 참조를 반환하지 말아라
- F.44: 복사를 권장하지 않거나 "개체를 항상 반환"한다면 T&를 반환하라
- F.45: T&&를 반환하지 말아라
- F.46: main()는 int를 반환해야 한다
- F.47: 대입 연산자는 T&를 반환하라
- F.48: return std::move(local)은 사용하지 말아라
기타 함수 규칙:
- F.50: 함수를 쓸 수 없을 때는 람다를 사용하라(지역 변수를 캡쳐하거나 지역 함수를 작성할 때)
- F.51: 선택할 수 있다면, 중복 정의보다는 기본 전달인자를 선호하라
- F.52: 지역적으로 사용된다면 람다의 참조 캡쳐를 선호하라
- F.53: 지역적으로 사용되지 않는다면 참조 캡쳐를 피하라
- F.54: this를 캡쳐할 때는, 모든 변수를 명시적으로 캡쳐하라(기본 캡쳐를 사용하지 않는다)
- F.55: va_arg 전달인자를 사용하지 말아라
함수는 하나의 논리적 동작만 수행해야 한다
하나의 작업만 수행하는 함수는 이해하기 쉽고, 테스트하기 쉽고, 재사용하기 쉽다.
void read_and_print() // bad
{
int x;
cin >> x;
// check for errors
cout << x << "\n";
}
int read(istream& is) // better
{
int x;
is >> x;
// check for errors
return x;
}
void print(ostream& os, int x)
{
os << x << "\n";
}
"출력"값 여러 개를 반환할 때는 튜플이나 구조체를 선호하라
반환 값은 그 자체로 문서가 필요하지 않고 "출력 전용"으로 사용된다. C++ 에서는 다수의 값을 반환할때는 tuple(pair를 포함해)를 쓴다는 것을 기억하라,
호출한 지점에서 tie를 사용해 받을 것이다. 반환 값에 의미구조가 있다면 별도의 struct 타입을 사용하라. 그렇지 않다면 일반적인 코드에서는 (이름 없는) tuple이 유용하다.
C++11에서는 이렇게 작성할 수 있다, 결과값들을 이미 존재하는 지역변수에 대입한다:
Sometype iter; // default initialize if we haven't already
Someothertype success; // used these variables for some other purpose
tie(iter, success) = my_set.insert("Hello"); // normal return value
if (success) do_something_with(iter);
C++ 17에서는 다수의 변수들을 선언과 동시에 초기화 할 수 있는 "structured bindings"을 지원한다:
if (auto [ iter, success ] = my_set.insert("Hello"); success) do_something_with(iter);
"인자가 없을 경우"를 허용한다면 T&보다는 T*를 선호하라
포인터(T*)는 nullptr일 수 있지만, 참조(T&)는 그렇지 않다.
경우에 따라서는 "개체 없음"을 표시하기 위해 nullptr를 사용하는 것이 유용할 수 있다. 그렇지 않다면, 참조가 더 간단하고 좋은 코드로 이어질 것이다.
string zstring_to_string(zstring p) // zstring is a char*; that is a C-style string
{
if (!p) return string{}; // p might be nullptr; remember to check
return string{p};
}
void print(const vector<int>& r)
{
// r refers to a vector<int>; no check needed
}
'프로그래밍 일반 > C++ Core Guildlines' 카테고리의 다른 글
C++ Core Guidlines 인터페이스 (0) | 2019.11.11 |
---|---|
C++ Core Guidlines 철학 (0) | 2019.11.11 |
C++ Core Guidlines 소개 (0) | 2019.11.11 |