Post

[Effective C++] Chapter 1 #1

[Effective C++] Chapter 1 #1

πŸ’™ref.

슀콧 λ§ˆμ΄μ–΄μŠ€, Effective C++ [3판], 곽용재(μ—­), ν”„λ‘œν…λ―Έλ””μ–΄, 2015


2. #define

ν•­λͺ© 2: #define을 μ“°λ €κ±°λ“  const, enum, inline을 λ– μ˜¬λ¦¬μž


define μ½”λ“œ 예제

1
#define ASPECT_RATIO 1.653

μ†ŒμŠ€ μ½”λ“œκ°€ 컴파일러둜 λ„˜μ–΄κ°€κΈ° 전에 μ„ ν–‰ μ²˜λ¦¬μžκ°€ ν•΄λ‹Ή μ½”λ“œλ₯Ό 숫자 μƒμˆ˜λ‘œ λ³€ν™˜μ‹œν‚¨λ‹€. 결과적으둜, ASPECT_RATIOλΌλŠ” 이름은 μ»΄νŒ‘λ¦¬λŸ¬κ°€ μ“°λŠ” 기호 ν…Œμ΄λΈ”μ— 듀어가지 μ•ŠλŠ”λ‹€!

숫자 μƒμˆ˜λ‘œ λŒ€μ²΄λœ μ½”λ“œμ—μ„œ 컴파일 μ—λŸ¬κ°€ λ°œμƒν•˜λ©΄ κ³€λž€ν•œ 상황이 λ°œμƒν•œλ‹€,

  • μ†ŒμŠ€ μ½”λ“œμ—” ASPECT_RATIOκ°€ μžˆμ—ˆλŠ”λ° μ—λŸ¬ λ©”μ‹œμ§€μ—” 1.653κ°€ 좜λ ₯됨
    • λ§Œμ•½, ν•΄λ‹Ή define이 μ •μ˜λœ μ½”λ“œκ°€ 직접 μž‘μ„±ν•œ 것이 μ•„λ‹ˆλΌλ©΄ μ–΄λŠ μ½”λ“œμΈμ§€ μ°ΎλŠ” 데 μ‹œκ°„μ„ λ‚­λΉ„ν•˜κ²Œ 됨
    • κΈ°ν˜Έμ‹ 디버거에도 같은 λ¬Έμ œκ°€ λ°œμƒν•  수 있음(기호 ν…Œμ΄λΈ”μ— 듀어가지 μ•ŠκΈ° λ•Œλ¬Έ)


μœ„ 예제 μ½”λ“œμ˜ ν•΄κ²°μ•ˆ

1
2
const double AspectRatio = 1.653
// λŒ€λ¬Έμžλ‘œλ§Œ ν‘œκΈ°ν•˜λŠ” 이름은 λŒ€κ°œ λ§€ν¬λ‘œμ— μ“°λŠ” κ²ƒμ΄λ―€λ‘œ, 이름 ν‘œκΈ°λ„ λ°”κΏ”μ£Όμ–΄μ•Ό ν•œλ‹€!
  • μ–Έμ–΄ μ°¨μ›μ—μ„œ μ§€μ›ν•˜λŠ” μƒμˆ˜ νƒ€μž…μ˜ λ°μ΄ν„°μ΄λ―€λ‘œ μ»΄νŒŒμΌλŸ¬λ„ 인식 κ°€λŠ₯
    • 컴파일러 기호 ν…Œμ΄λΈ”μ— μ €μž₯
    • μƒμˆ˜κ°€ λΆ€λ™μ†Œμˆ˜μ  μ‹€μˆ˜ νƒ€μž…μΌ 경우, μ»΄νŒŒμΌμ„ 거친 μ΅œμ’… μ½”λ“œμ˜ 크기가 #define보닀 μž‘κ²Œ λ‚˜μ˜¬ 수 있음
      • #define의 경우 1.653의 사본이 λ“±μž₯ νšŸμˆ˜λ§ˆλ‹€ λ§Œλ“€μ–΄μ§€μ§€λ§Œ, μƒμˆ˜ νƒ€μž…μΌ 경우 λ”± ν•œ 개만 생성


1. #define => μƒμˆ˜ ꡐ체 μ‹œ μ£Όμ˜μ‚¬ν•­

1.1. μƒμˆ˜ 포인터 μ •μ˜

  • μƒμˆ˜ 포인터(constant pointer) μ •μ˜

    • λŒ€κ°œ 헀더 νŒŒμΌμ—μ„œ μƒμˆ˜λ₯Ό μ •μ˜ν•˜λ―€λ‘œ, 포인터λ₯Ό λ°˜λ“œμ‹œ const둜 μ„ μ–Έ

    • 포인터가 κ°€λ¦¬ν‚€λŠ” λŒ€μƒλ„ ν•¨κ»˜ const둜 μ„ μ–Έν•˜λŠ” 것이 μΌλ°˜μ μž„

      eg) μ–΄λ–€ 헀더 파일 μ•ˆμ— char* 기반의 λ¬Έμžμ—΄ μƒμˆ˜λ₯Ό μ •μ˜ν•  경우, constλ₯Ό 두 번 기재

      const char * const authorName = "Scott Meyers";

      const std::string authorName("Scott Meyers"); => string객체 μ‚¬μš©μ„ ꢌμž₯!


2. 클래슀 λ©€λ²„λ‘œ μƒμˆ˜ μ •μ˜

μ–΄λ–€ μƒμˆ˜μ˜ μœ νš¨λ²”μœ„λ₯Ό 클래슀둜 ν•œμ •ν•  경우, 사본 κ°œμˆ˜κ°€ ν•œ 개λ₯Ό λ„˜μ§€ λͺ»ν•˜κ²Œ ν•˜κ³  μ‹Άλ‹€λ©΄ 정적 λ©€λ²„λ‘œ μ„ μ–Έν•˜μž.

1
2
3
4
5
6
class GamePlayer{
private:
	static const int NumTurns = 5;	// μƒμˆ˜ μ„ μ–Έ
    int scores[NumTurns];			// μƒμˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” λΆ€λΆ„
	...
};
  • μ½”λ“œ μž‘μ„± μ‹œ μ„ μ–Έ ν›„ μ •μ˜λΆ€λ₯Ό μž‘μ„±ν•˜λŠ” 것이 μΌλ°˜μ μž„

  • 정적 λ©€λ²„λ‘œ λ§Œλ“€μ–΄μ§€λŠ” μ •μˆ˜λ₯˜ νƒ€μž…μ˜ 클래슀 μƒμˆ˜λŠ” μ •μ˜ λ§ˆλ ¨ν•˜μ§€ μ•ŠμŒ

    • 클래슀 μƒμˆ˜μ˜ μ£Όμ†Œλ₯Ό ꡬ할 κ²½μš°μ—λ§Œ μ •μ˜λΆ€ κ΅¬ν˜„

      const int GamePlayer::NumTurns;

      • λ³„λ„μ˜ μ •μ˜λ₯Ό κΈ°μž¬ν•  경우, 값을 μ œκ³΅ν•˜μ§€ μ•ŠμŒ
        • μ΄λ•Œ, 클래슀 μƒμˆ˜μ˜ μ •μ˜λŠ” κ΅¬ν˜„ νŒŒμΌμ— 기재
        • 클래슀 μƒμˆ˜μ˜ μ΄ˆκΈ°κ°’μ€ ν•΄λ‹Ή μƒμˆ˜κ°€ μ„ μ–Έλœ μ‹œμ μ— λ°”λ‘œ μ΄ˆκΈ°ν™”


μƒμˆ˜ λŒ€μ²΄ μ‹œ μ£Όμ˜μ‚¬ν•­

  • 클래슀 μƒμˆ˜λŠ” #define으둜 λ§Œλ“€μ§€ 말자

    • #define은 클래슀 μƒμˆ˜λ₯Ό μ •μ˜ν•˜λŠ”λ° μ‚¬μš©ν•  수 x

    • μ–΄λ–€ ν˜•νƒœμ˜ μΊ‘μŠν™” ν˜œνƒλ„ 받을 수 μ—†μŒ

      eg) private ν˜•νƒœμ˜ #define ꡬ문은 μ‘΄μž¬ν•˜μ§€ μ•ŠμŒ




1.2. 클래슀 멀버 μ΄ˆκΈ°ν™”κ°€ μ–΄λ €μš΄ 경우

μ»΄νŒŒμΌλŸ¬κ°€ 정적 클래슀 멀버가 μ„ μ–Έλœ μ‹œμ μ— μ΄ˆκΈ°κ°’μ„ μ£ΌλŠ” 것이 λ§žμ§€ μ•ŠλŠ”λ‹€κ³  νŒλ‹¨ν•  경우, μ΄ˆκΈ°κ°’μ€ μƒμˆ˜ μ •μ˜ μ‹œμ μ— κΈ°μž¬ν•˜μž.

1
2
3
4
5
6
7
8
class CostEstimate {
private:
    static const double FudgeFactor;
    ...
};

// 정적 클래슀 μƒμˆ˜μ˜ μ •μ˜ => κ΅¬ν˜„ νŒŒμΌμ— 적자!
const double CostEstimate::FudgeFactor = 1.35;
  • μ΄λ•Œ, ν•΄λ‹Ή 클래슀λ₯Ό μ»΄νŒŒμΌν•˜λŠ” 도쀑 클래슀 μƒμˆ˜μ˜ 값이 ν•„μš”ν•œ κ²½μš°κ°€ 생김

    • GamePlayer::scoresκ³Ό 같이 λ°°μ—΄ 멀버 μ„ μ–Έ

      => β€œλ‚˜μ—΄μž λ‘”κ°‘μˆ (enmu hack)” 기법을 μ‚¬μš©ν•΄ ν•΄κ²° κ°€λŠ₯


1
2
3
4
5
6
7
8
class GamePlayer {
private:
    // "λ‚˜μ—΄μž λ‘”κ°‘μˆ ": NumTurnsλ₯Ό 5에 λŒ€ν•œ κΈ°ν˜Έμ‹ μ΄λ¦„μœΌλ‘œ λ§Œλ“ λ‹€.
    enum { NumTurns = 5 };	
    
    int scores[NumTurns];
    ...
};
  • λ‚˜μ—΄μž λ‘”κ°‘μˆ 

    • λ™μž‘ 방식이 const보닀 #define에 κ°€κΉŒμ›€

      • const의 μ£Όμ†Œλ₯Ό μž‘μ•„λ‚΄λŠ” 것은 ν•©λ‹Ήν•˜λ‚˜, enum의 μ£Όμ†Œλ₯Ό ν•¨λΆ€λ‘œ μž‘μ„ 수 x

        (=> #defineκ³Ό μœ μ‚¬ν•¨!!)

      • κ°œλ°œμžκ°€ μ„ μ–Έν•œ μ •μˆ˜ μƒμˆ˜μ˜ μ£Όμ†Œλ₯Ό λ‹€λ₯Έ μ‚¬λžŒμ΄ μ–»λŠ” 게 싫을 경우

      • const 객체에 λŒ€ν•œ λ©”λͺ¨λ¦¬λ₯Ό λ§Œλ“€κ³  싢지 μ•Šμ„ 경우

        (=> enum의 경우 μ–΄λ–€ ν˜•νƒœμ˜ μ“Έλ°μ—†λŠ” λ©”λͺ¨λ¦¬ 할당을 ν•˜μ§€ μ•ŠμŒ)

    • ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ˜ 핡심 기술이 됨



2.1. 였용 사둀

맀크둜 ν•¨μˆ˜

1
2
// a와 b 쀑 큰 것을 f둜 λ„˜κΉ€
#define CALL_WHTH_MAX(a, b) f((a) > (b) ? (a) : (b))
  • ν•¨μˆ˜μ²˜λŸΌ λ³΄μ΄μ§€λ§Œ ν•¨μˆ˜ 호좜 μ˜€λ²„ν—€λ“œλ₯Ό μΌμœΌν‚€μ§€ μ•ŠλŠ” 맀크둜 κ΅¬ν˜„
    • 이런 μ‹μ˜ λ§€ν¬λ‘œλŠ” 단점이 많음. ꢌμž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.
    • 맀크둜 본문에 λ“€μ–΄ μžˆλŠ” μΈμžλ§ˆλ‹€ λ°˜λ“œμ‹œ κ΄„ν˜Έλ₯Ό μ”Œμ›Œ 주자.
      • κ΄„ν˜Έκ°€ μ—†μœΌλ©΄ ν‘œν˜„μ‹μ„ λ§€ν¬λ‘œμ— λ„˜κΈΈ λ•Œ 였λ₯˜κ°€ λ°œμƒν•  수 있음


1
2
3
4
int a = 5, b = 0;

CALL_WHTH_MAX(++a, b);		// a 두 번 증가
CALL_WHTH_MAX(++a, b+10);	// a ν•œ 번 증가 
  • fκ°€ 호좜되기 전에 aκ°€ μ¦κ°€ν•˜λŠ” νšŸμˆ˜κ°€ 달라짐
    • 비ꡐλ₯Ό 톡해 μ²˜λ¦¬ν•œ κ²°κ³Όκ°€ μ–΄λ–€ 것이냐에 따라 달라진닀(ν”„λ‘œκ·Έλž¨μ— 올 λ°œμƒ)


단점 κ°œμ„ ν•œ μ½”λ“œ

1
2
3
4
5
template<typename T>
inline void callWithMax(const T& a, const T& b)
{
	f(a > b ? a : b);
}
  • ν…œν”Œλ¦Ώμ΄κΈ° λ•Œλ¬Έμ— 동일 계열 ν•¨μˆ˜κ΅°(family of functions)을 생성

    • λ™μΌν•œ νƒ€μž…μ˜ 객체 두 개λ₯Ό 인자둜 λ°›κ³  λ‘˜ 쀑 큰 κ²ƒμœΌλ‘œ f둜 λ„˜κ²¨ 호좜

    • ν•¨μˆ˜ 본문에 κ΄„ν˜Έλ₯Ό μ“Έ ν•„μš” x

    • 인자λ₯Ό μ—¬λŸ¬ 번 ν‰κ°€ν•˜μ§€ μ•ŠμŒ

    • callWithMaxλŠ” μ‹€μ œλ‘œ κ΅¬ν˜„λœ ν•¨μˆ˜μ΄λ―€λ‘œ μœ νš¨λ²”μœ„ 및 μ ‘κ·Όκ·œμΉ™μ„ κ·ΈλŒ€λ‘œ 따라감

      • cf) μž„μ˜μ˜ ν΄λž˜μŠ€μ—μ„œλ§Œ μ‚¬μš©ν•  수 μžˆλŠ” 인라인 ν•¨μˆ˜μ— λŒ€ν•΄μ„œλ„ λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•ŠμŒ

        ​ λ§€ν¬λ‘œλŠ” 이런 이야기에 λŒ€ν•΄ κ΄€λ ¨ x


*πŸͺ„Conclusion)* **
1. λ‹¨μˆœν•œ μƒμˆ˜λ₯Ό μ“Έ λ•ŒλŠ”, #define 보닀 const ν˜Ήμ€ enum을 μš°μ„  μƒκ°ν•˜μž.
2. ν•¨μˆ˜μ²˜λŸΌ λ³΄μ΄λŠ” 맀크둜λ₯Ό λ§Œλ“€λ €λ©΄ #define보닀 인라인 ν•¨μˆ˜λ₯Ό μš°μ„  μƒκ°ν•˜μž.

This post is licensed under CC BY 4.0 by the author.

Β© yejin. Some rights reserved.