U E D R , A S I H C RSS

More EffectiveC++/Techniques1of3

MoreEffectiveC++

Contents

1. Techniques
1.1. Item 25: Virtualizing constructors and non-member functions
1.1.1. Virtual Constructor : ๊ฐ€์ƒ ์ƒ์„ฑ์ž
1.1.2. Making Non-Member Functions Act Virtual : ๋น„๋ฉค๋ฒ„ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ƒ ํ•จ์ˆ˜์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๊ธฐ
1.2. Item 26: Limiting the number of objects of a class
1.2.1. Allowing Zero or One Objects : 0 ํ˜น์€ ํ•˜๋‚˜์˜ ๊ฐ์ฒด ๋งŒ์„ ํ—ˆ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
1.2.2. Context for Object Construction : ๊ฐ์ฒด์˜ ์ƒ์„ฑ์„ ์œ„ํ•œ ๊ตฌ๋ฌธ(๊ด€๊ณ„, ๋ฌธ๋งฅ, ์ƒํ™ฉ)
1.2.3. Allowing Objects to Come and Go : ๊ฐ์ฒด๊ฐ€ ์˜ค๊ณ  ๊ฐ์„ ํ—ˆ์šฉํ•˜๊ธฐ?
1.2.4. An Object-Counting Base Class : Object-counting์— ๊ธฐ๋ณธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋ณธ๋‹ค.
1.3. Item 27: Requiring or prohibiting heap-based objects.
1.3.1. Requiring Heap-Based Objects : Heap ๊ธฐ๋ฐ˜ ๊ฐ์ฒด๋“ค์ด ํ•„์š”
1.3.2. Determining Whether an Object is On The Heap : Heap์— ๊ฐ์ฒด๋ฅผ ์˜ฌ๋ฆด์ง€ ๊ฒฐ์ •ํ•˜๊ธฐ.
1.3.3. Prohibiting Heap-Based Objects : Heap์˜์—ญ์— ๊ฐ์ฒด ์˜ฌ๋ฆฌ๊ธฐ ๋ง‰๊ธฐ
1.4. Item 28: Smart pointers
1.4.1. Construction, Assignment and Destruction of Smart Pointers : ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ์ƒ์„ฑ, ํ• ๋‹น, ํŒŒ๊ดด
1.4.2. Implementing the Dereferencing Operators : ์—ญ์ฐธ์กฐ(Dereferencing) ์—ฐ์‚ฐ์ž์˜ ์ ์šฉ
1.4.3. Testing Smart Pointers for Nullness : ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ๋”๋ฏธ(dumb)์ƒ์˜ null ์—ฌ๋ถ€๋ฅผ ์•Œ๊ณ  ์‹ถ์–ด!

1. Techniques

1.1. Item 25: Virtualizing constructors and non-member functions

  • Item 25: ์ƒ์„ฑ์ž์™€ ๋น„๋ฉค๋ฒ„ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ƒ์œผ๋กœ ๋Œ์•„๊ฐ€๊ฒŒ ํ•˜๊ธฐ.

1.1.1. Virtual Constructor : ๊ฐ€์ƒ ์ƒ์„ฑ์ž

๊ฐ€์ƒ ์ƒ์„ฑ์ž, ์ด๊ฒƒ์— ๊ด€ํ•ด์„œ ์ƒ๊ฐํ•ด ๋ณด๊ธฐ๋Š” ์ข€ ์ƒ์†Œํ•˜๋‹ค. ์‚ฌ์‹ค ๊ฐ€์ƒ ํ•จ์ˆ˜๋ฅผ ๋ถ€๋ฅผ๋ ค๋ฉด, ๊ฐ์ฒด์—๋Œ€ํ•œ ์ฐธ์กฐ๋‚˜, ํฌ์ธํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•˜๋Š”๋ฐ, ์ƒ์„ฑํ• ๋•Œ ๋ถ€ํ„ฐ ๊ฐ€์ƒ(virtual) ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค? ์ข€ ์ด์ƒํ•˜์ง€ ์•Š์€๊ฐ€? ์–ด๋–จ๋•Œ, ์–ด๋–ป๊ฒŒ ์ด ๊ฐ€์ƒ ์ƒ์„ฑ์ž ๋ผ๋Š”๊ฑธ ์จ๋จน์„์ˆ˜ ์žˆ์„๊บผ?

์‚ฌ์‹ค ๊ฐ€์ƒ ์ƒ์„ฑ์ž๋ผ๋Š”๊ฑด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฅผ ๋น„์Šทํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์˜ˆ๋ฅผ๋“ค์ž๋ฉด ๋‹น์‹ ์ด newsletter์„ ๋ณด๋‚ด๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์งœ๋Š”๋ฐ, ์—ฌ๊ธฐ์— ๊ธ€๊ณผ ๊ทธ๋ฆผ ๋ฐ์ดํ„ฐ ์ธ์ž๋กœ ๊ตฌ์„ฑ์‹œํ‚จ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

~cpp 
class NLComponent{                      // News Letter ์˜ ๋ถ€๋ชจ ์ธ์ž
public:
    ...
};
class TextBlock:public NLComponent{     // ๊ธ€์„ ํ‘œํ˜„ํ•˜๋Š” ์ธ์ž
public:
    ...
};
class Graphic:public NLComponent{       // ๊ทธ๋ฆผ์„ ํ‘œํ˜„ํ•˜๋Š” ์ธ์ž
public:
    ...
};
class NewsLetter {                       // ๊ธ€๊ณผ, ๊ทธ๋ฆผ์„ ๊ฐ€์ง€๋Š” News Letter
public:
    ...
private:
    list<NLComponent*> components;      // ๊ธ€๊ณผ ๊ทธ๋ฆผ ์ธ์ž์˜ ์ €์žฅ์†Œ
};
์ด๋Ÿฐ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„๋œ๋‹ค.


list ํด๋ž˜์Šค๋Š” STL๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋Š”๋ฐ, Item 35๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ์ •๋ณด๋ฅผ ์–ป์„์ˆ˜ ์žˆ๋‹ค. ๋‹จ์ˆœํžˆ ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์Šคํฌ(double linked list)๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฌด๋ฆฌ๊ฐ€ ์—†์„ ๊ฒƒ์ด๋‹ค.

NewsLetter ๊ฐ์ฒด๋Š” ์•„๋งˆ ๋””์Šคํฌ์—์„œ ์ž๋ฃŒ๋ฅผ ์ ์žฌํ•  ๊ฒƒ์ด๋‹ค. NewsLetter๊ฐ€ ๋””์Šคํฌ์—์„œ ์ž๋ฃŒ๋ฅผ ๊ฐ€์ง€๊ณ  ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด istream์„ ์‚ฌ์šฉํ•ด์„œ NewsLetter๋ฅผ ๊ตฌ์„ฑํ•  ๊ฐ์ฒด๋“ค์„ ์ƒ์„ฑํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋“ค์„ ๋Œ€๊ฐ• ๋งŒ๋“ค์ˆ˜ ์žˆ๋Š”๋ฐ

~cpp 
class NewsLetter {
public:
    NewsLetter(istream& str);
    ...
};
๊ฐ€์งœ ์ฝ”๋“œ๋กœ ์ด ์ƒ์„ฑ์ž๋ฅผ ๋Œ€๊ฐ• ํ‘œํ˜„ํ•˜๋ฉด

~cpp 
NewsLetter::NewsLetter(istream& str)
{
    while(str){
        ๋‹ค์Œ์— ์ถ”๊ฐ€๋  ์ธ์ž ๊ฐ์ฒด(component object)๋ฅผ str๋กœ ๋ถ€ํ„ฐ ์ฝ๋Š”๋‹ค.

        newsletter์˜ ์ธ์ž์ค‘ ๋ฆฌ์ŠคํŠธ์ธ components์— ๋งŒ๋“  ๊ฐ์ฒด๋ฅผ ๋„ฃ๋Š”๋‹ค.
    }
}
ํ˜น์€ ์•ฝ๊ฐ„ ์ˆ˜๋ฅผ ์จ์„œ readComponent๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์‹์œผ๋กœ ๋ฐ”๊พผ๋‹ค๋ฉด

~cpp 
class NewsLetter{
publicc:
    ...
private:
    // ์ˆœ์ˆ˜ํžˆ ๋””์Šคํฌ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด ๋“œ๋ฆฌ๋Š” istream๊ณผ ์ž๋ฃŒ str์—์„œ
    // ํ•ด๋‹น ์ž๋ฃŒ๋ฅผ ํ•ด์„ํ•˜๊ณ , ์•Œ๋งž๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฐ˜ํ˜ธ๋‚˜ํ•˜๋Š” readComponent๊ฐ์ฒด
    static NLComponent * readComponent(istream& str);
};
NewsLetter::NewsLetter(istream& str)
{
    while (str) {
        // readComponent๊ฐ€ ํ•ด์„ํ•œ ๊ฐ์ฒด๋ฅผ newsletter์˜ ๋ฆฌ์ŠคํŠธ ๋งˆ์ง€๋ง‰์— ์ถ”๊ฐ€์‹œํ‚ค๋Š” ๊ณผ์ •
        components.push_back(readComponent(str));
    }
}
readComponent๊ฐ€ ๋ฌด์—‡์„ ์–ด๋–ป๊ฒŒ ํ•˜๋Š”์ง€ ๊ถ๋ฆฌํ•ด ๋ณด์ž. ์œ„์— ์–ธ๊ธ‰ํ•œ๋“ฏ์ด readComponent๋Š” ๋ฆฌ์ŠคํŠธ์— ๋„ฃ์„ TextBlock๋‚˜ Graphicํ˜•์˜ ๊ฐ์ฒด๋ฅผ ๋””์Šคํฌ์—์„œ ์ฝ์–ด ๋“œ๋ฆฐ ์ž๋ฃŒ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋งŒ๋“ค์–ด ๋‚ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ตœ์ข…์ ์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ํ•ด๋‹น ๊ฐ์ฒด์˜ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์„œ list์˜ ์ธ์ž๋ฅผ ๊ตฌ์„ฑํ•˜๊ฒŒ ํ•ด์•ผ ํ• ๊ฒƒ์ด๋‹ค. ์ด๋•Œ ๋งˆ์ง€๋ง‰ ์ฝ”๋“œ์—์„œ ๊ฐ€์ƒ ์ƒ์„ฑ์ž์˜ ๊ฐœ๋…์ด ๋งŒ๋“ค์–ด ์ ธ์•ผ ํ• ๊ฒƒ์ด๋‹ค. ์ž…๋ ฅ๋˜ ๋Š”์ž๋ฃŒ์— ๊ธฐ์ดˆ๋˜์–ด์„œ, ์•Œ์•„์„œ ๋งŒ๋“ค์–ด ์ธ์ž. ๊ฐœ๋…์ƒ์œผ๋กœ๋Š” ์˜ณ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๊ทธ๋ ‡๊ฒŒ ๊ตฌํ˜„๋ ์ˆ˜๋Š” ์—†์„ ๊ฒƒ์ด๋‹ค. ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ• ๋•Œ ๋ถ€ํ„ฐ ํ˜•์„ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•˜๋Š”๊ฑด ์ž๋ช…ํ•˜๋‹ˆ๊นŒ. ๊ทธ๋ ‡๋‹ค๋ฉด ๋น„์Šทํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด ๋ณธ๋‹ค?

๊ฐ€์ƒ ์ƒ์„ฑ์ž์˜ ๋ฐฉ์‹์˜ ํ•œ ์ข…๋ฅ˜๋กœ ํŠน๋ณ„ํ•˜๊ฒŒ ๊ฐ€์ƒ ๋ณต์ž ์ƒ์„ฑ์ž(virtual copy constructor)๋Š” ๋„๋ฆฌ ์“ฐ์ธ๋‹ค. ์ด ๊ฐ€์ƒ ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋Š” ์ƒˆ๋กœ์šด ์‚ฌ๋ณธ์˜ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ copySlef๋‚˜ cloneSelf๊ฐ™์€ ๋ณต์‚ฌ์˜ ๊ฐœ๋…์œผ๋กœ ์ƒ์„ฑ์ž๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ์—์„œ๋Š” clone์˜ ์ด๋ฆ„์„ ์“ฐ์˜€๋‹ค.

~cpp 
class NLComponent{
public:
    // ๊ฐ€์ƒ ๋ณต์‚ฌ ์ƒ์„ฑ์ž virtual copy constructor ์„ ์–ธ
    virtual NLComponent * clone() const = 0;
    ...
};
class TextBlock: public NLComponent{
public:
    virtual TextBlock * clone() const // ๊ฐ€์ƒ ๋ณต์‚ฌ ์ƒ์„ฑ์ž ์„ ์–ธ
    { return new TextBlock(*this); }
    ...
};
class Graphic:public NLComponent{
public:
    virtual Graphic * clone() const // ๊ฐ€์ƒ ๋ณต์‚ฌ ์ƒ์„ฑ์ž ์„ ์–ธ
    { return new Graphic(*this); }
    ...
};
๋ณด๋‹ค์‹œํ”ผ ํด๋ž˜์Šค์˜ ๊ฐ€์ƒ ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋Š” ์‹ค์ œ ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ "๋ณต์‚ฌ" ์˜๋ฏธ๋กœ๋Š” ์ผ๋ฐ˜ ๋ณต์‚ฌ ์ƒ์„ฑ์ž์™€ ์ˆ˜ํ–‰ ๊ธฐ๋Šฅ์ด ๊ฐ™๋‹ค ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์ ์€ ๋งŒ๋“ค์–ด์ง„ ๊ฐ์ฒด๋งˆ๋‹ค ์ œ๊ฐ๊ฐ์˜ ์•Œ๋งž๋Š” ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ ๋‹ค๋Š” ์ ์ด ๋‹ค๋ฅด๋‹ค. ์ด๋Ÿฐ clone์ด NewsLetter ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค๋•Œ NLComponent๋“ค์„ ๋ณต์‚ฌํ•˜๋Š”๋ฐ ๊ธฐ์—ฌ๋ฅผ ํ•œ๋‹ค. ์–ด๋–ป๊ฒŒ ๋” ์‰ฌ์šด ์ž‘์—…์ด ๋˜๋Š”์ง€ ๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ๋ณด๋ฉด ์ดํ•ด ํ• ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

~cpp 
class NewsLetter{
public:
    NewsLetter(const NewsLetter* rhs);  // NewsLetter์˜ ๋ณต์‚ฌ ์ƒ์„ฑ์ž
    ...
private:
    list<NLComponent *> components;
};
NewsLetter::NewsLetter(const NewsLetter* rhs)
{
    for (list<NLComponent*>::constiterator it = rhs.components.begin(); 
        it != rhs.components.end(); 
        ++it){
        // it์€ rhs.components์˜ ํ˜„์žฌ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ธ์ž๋กœ, ๋ณต์‚ฌ๋˜์–ด์•ผ ํ•  ๊ฐ์ฒด์ด๋‹ค.
        // ํ˜•์„ ๊ฐ€๋ฆฌ๋Š” ์ž‘์—… ์—†์ด ๊ทธ๋ƒฅ clone์„ ์ด์šฉํ•ด ๊ณ„์† ๋ณต์‚ฌํ•ด ๋ฒ„๋ฆฌ๋ฉด ๊ฐ ํ˜•์— ์•Œ๋งž๋Š” ๋ณต์‚ฌ
        // ์ƒ์„ฑ์ž๊ฐ€ ๋ถˆ๋ฆฌ๋ฉด์„œ ๋ณต์‚ฌ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
        components.push_back((it*)->clone());
    }
}
STL์ด ์ƒ์†Œํ•˜๋‹ค๋ฉด ๋‚˜์ค‘์— ์ตํ˜€๋ผ ํ•˜์ง€๋งŒ ์œ„์˜ ์•„์ด๋””์–ด๋Š” ์ฃผ์„๋ฌธ์œผ๋กœ ์ธํ•ด ์ดํ•ด๊ฐ€ ๊ฐˆ๊ฒƒ์ด๋‹ค. ๊ฐ€์ƒ ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋กœ ์ธํ•ด์„œ, ๊ฐ์ฒด ๋ณต์‚ฌ๊ฐ€ ์ƒ๋‹นํžˆ ๊ฐ„ํŽธํ•ด ์ง„๋‹ค.

1.1.2. Making Non-Member Functions Act Virtual : ๋น„๋ฉค๋ฒ„ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ƒ ํ•จ์ˆ˜์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๊ธฐ

์ƒ์„ฑ์ž๋Š” ์‹ค์ œ๋กœ ๊ฐ€์ƒ ํ•จ์ˆ˜๊ฐ€ ๋ ์ˆ˜ ์—†๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋น„๋ฉค๋ฒ„ ํ•จ์ˆ˜๋“ค ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€ ์ด๋ฆฌ๋ผ, ํ•˜์ง€๋งŒ ๊ทธ๋Ÿฌํ•œ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•  ๋–„๊ฐ€ ์žˆ๋‹ค. ๋ฐ”๋กœ ์•ž ์˜ˆ์ œ์—์„œ NLComponent์™€ ๊ทธ๊ฒƒ์—์„œ ์œ ๋„๋œ ํด๋ž˜์Šค๋“ค์„ ์˜ˆ๋ฅผ ๋“ค์–ด ๋ณด์ž๋ฉด ์ด๋“ค์„ operator<<์œผ๋กœ ์ถœ๋ ฅ์„ ํ•„์š”๋กœ ํ• ๋•Œ ์ด๋ฆฌ๋ผ. ๋ญ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ฉด ๋ฌธ์ œ ์—†๋‹ค.

~cpp 
class NLComponent{
public:
    // operator<<์˜ ๊ฐ€์ƒ ํ•จ์ˆ˜
    virtual ostream& operator<<(ostream& str) const = 0;
    ...
};
class TextBlock:public NLComponent{
public:
    virtual ostream& operator<<(ostream& str) const;
};
class Graphic:public NLComponent{
public:
    virtual ostream& operator<<(ostream& str) const;
};

TextBlock t;
Graphic g;
...
t << cout;

g << cout;
ํ•˜์ง€๋งŒ ์ถœ๋ ฅํ•ด์•ผํ•  ์ŠคํŠธ๋ฆผ ๊ฐ์ฒด๊ฐ€ righ-hand ๊ฐ์ฒด๋ผ๋Š”๊ฒƒ์ด ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ ๋ถˆํŽธํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๋ณดํ†ต ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ŠคํŠธ๋ฆผ ๊ฐ์ฒด์— ์ถœ๋ ฅํ•  ๊ฐ์ฒด๋ฅผ ๋„ฃ๋Š” ๋‹ค๋Š” ๊ฐœ๋…์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์ด๋ฆฌ๋ผ. ํ•˜์ง€๋งŒ, ์ „์—ญ ํ•จ์ˆ˜๋‚˜ friendํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด ๋”์ด์ƒ ๊ฐ€์ƒํ•จ์ˆ˜๋กœ ๊ตฌํ˜„ํ• ์ˆ˜๊ฐ€ ์—†๊ฒŒ ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ์˜ ๋ฐฉ๋ฒ•์ด ๋น„๋ฉค๋ฒ„ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ€์ƒ ํ•จ์ˆ˜๋กœ ์ถœ๋ ฅ์„ ๊ตฌํ˜„ํ•˜๊ณ , ์ „์—ญ์ด๋“ , namespace๋กœ ๋ฌถ์—ฌ ์žˆ๋“ , ๋น„ ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋กœ ์ŠคํŠธ๋ฆผ ๊ฐ์ฒด์™€์˜ ์ถœ๋ ฅ์˜ ๊ณ ๋ฆฌ๋ฅผ ์—ฐ๊ฒฐ์‹œ์ผœ์„œ, ๋น„๋ฉค๋ฒ„ ํ•จ์ˆ˜๊ฐ€ ๊ฐ€์ƒํ•จ์ˆ˜์ฒ˜๋Ÿผ ๋Œ์•„๊ฐ€๋„๋ก ๊ตฌํ˜„ํ•œ๋‹ค.

~cpp 
class NLComponent {
public:
  virtual ostream& print(ostream& s) const = 0;
  ...
};

class TextBlock: public NLComponent {
public:
  virtual ostream& print(ostream& s) const;
  ...
};

class Graphic: public NLComponent {
public:
  virtual ostream& print(ostream& s) const;
  ...
};

inline
ostream& operator<<(ostream& s, const NLComponent& c)
{
  return c.print(s);
}
๊ฐ€์ƒ ํ•จ์ˆ˜์˜ ์—ญํ• ์„ ๋น„๋ฉค๋ฒ„(non-member)ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„ํ•œ ์‚ฌ๋ก€์ด๋‹ค. ๋น„ ๋ฉค๋ฒ„ ํ•จ์ˆ˜์ด์ง€๋งŒ inline์„ ํ†ตํ•ด์„œ ๊ฐ€์ƒ ํ•จ์ˆ˜์™€์˜ ์ง์ ‘ ์—ฐ๊ฒฐ ํ†ต๋กœ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

๋น„๋ฉค๋ฒ„ ํ•จ์ˆ˜์˜ ๊ฐ€์ƒ(virtual)๊ด€๋ จ ์‚ฌ์šฉ์— ๋Œ€ํ•˜์—ฌ ๋” ๋‹ค๋ฃจ์ž๋ฉด ๋‚ด์šฉ์ด ๋ณต์žกํ•ด ์ง„๋‹ค. ์ด์— ๋Œ€ํ•œ ๊ด€๋ จ ์‚ฌํ•ญ์€ Item 31์„ ์ฐธ๊ณ ํ•˜๋ผ

1.2. Item 26: Limiting the number of objects of a class

  • Item 26: ๊ฐ์ฒด ์ˆซ์ž ์ œํ•œํ•˜๊ธฐ.

์ž ์ง€๊ธˆ๊นŒ์ง€ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋กœ ๋‹น์‹ ์€ ๋ฏธ์น  ์ง€๊ฒฝ์— ๋น ์กŒ์„ ๊บผ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ์ด๊ฒƒ์€ ๋‹น์‹ ์„ ํ˜ผ๋ž€์— ๋น ํŠธ๋ฆด ์ˆ˜์ค€๊นŒ์ง€ ์™”์„ ๊ฒƒ์ด๋‹ค. (์ฒซ์ค„๋งŒ ์ง๋…์งํ•ด.) ์˜ˆ๋ฅผ๋“ค์–ด์„œ ๋‹น์‹ ์˜ ์‹œ์Šคํ…œ์— ํ”„๋ฆฐํ„ฐ๊ฐ€ ํ•˜๋‚˜ ๋ฐ–์— ์—†์„๋•Œ ํ”„๋ฆฐํ„ฐ๋ฅผ ๋Œ€๋ณ€ํ•˜๋Š” ๊ฐ์ฒด์˜ ์ˆซ์ž๋ฅผ ํ•˜๋‚˜๋กœ ์ œํ•œํ•ด์•ผ ํ•˜์ง€ ์•Š์„๊นŒ? ์•„๋‹ˆ๋ฉด ํ•˜๋‚˜์˜ ํŒŒ์ผ์— ๋Œ€ํ•˜์—ฌ 16๊ฐœ์˜ ํŒŒ์ผ ์ ‘๊ทผ์ž๋งŒ ํ—ˆ์šฉํ• ๋•Œ ๋”ฐ์œ„ ๊ฐ™์€๊ฑฐ ๋ง์ด๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๊ทธ ํ•ด๋ฒ•์— ๊ด€ํ•ด์„œ ์ƒ๊ฐํ•ด ๋ณธ๋‹ค.
  • ์ž‘์„ฑ์ž์ฃผ : ์ด ๋ถ€๋ถ„์€ Singleton ํŒจํ„ด๊ณผ ์—ฐ๊ด€ํ•ด์„œ ์ƒ๊ฐํ•˜๋ฉด ์žฌ๋ฏธ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. Singleton ํŒจํ„ด์ด DP์— ๋…ผ์˜๋ ๋•Œ ์ด๊ฒƒ์„ ๊ฐ์•ˆ ์•ˆํ•œ๊ฒƒ์ด ์•„์‰ฝ๋‹ค. 1995๋…„์— ๋ฐœ๊ฐ„์ด๋ผ STL๋„ ์ œ๋Œ€๋กœ ๋‹ค๋ฃจ์ง€ ์•Š์•˜๊ณ , C++์˜ ๊ธฐ๋ณธ์ ์ธ ๋ฌธ๋ฒ•์„ ์ด์šฉํ•ด ๊ตฌํ˜„ํ•˜์˜€๋‹ค. MEC++๋Š” Techniques ๋ถ€๋ถ„์€ C++์˜ ๋ฌธ๋ฒ•๊ณผ ๊ฐœ๋…์„ ๊ทนํ•œ์œผ๋กœ ์“ด๋‹ค๋Š” ๋А๋‚Œ์ด ๋“ ๋‹ค.

1.2.1. Allowing Zero or One Objects : 0 ํ˜น์€ ํ•˜๋‚˜์˜ ๊ฐ์ฒด ๋งŒ์„ ํ—ˆ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•


๊ฐ์ฒด๋“ค์ด ์ƒ์„ฑ๋ ๋•Œ ๊ผญ ํ•˜๋Š” ์ผ์ด ์žˆ๋‹ค. ๋ฐ”๋กœ ์ƒ์„ฑ์ž๋ฅผ ๋ถ€๋ฅด๋Š” ์ผ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฑธ ๋ง‰์„์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ? ๊ฐ€์ƒ ์ฅ์šด ๋ฐฉ๋ฒ•์€ ์ƒ์„ฑ์ž๋ฅผ private(์‚ฌ์—ญ)์ธ์ž๋กœ ๋ฌถ์–ด ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค. ๋‹ค์Œ์„ ๋ณด์ž

~cpp 
class CantBeInstantiated {
private:
    CantBeInstantiated();
    CantBeInstantiated(const CantBeInstantiated&);
    ...
};
์ž ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ƒ์„ฑ์ž๊ฐ€ private์ƒํƒœ๋ผ์„œ ์™ธ๋ถ€์—์„œ ์ƒ์„ฑ์ž๋ฅผ ๋ถ€๋ฅผ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์™ธ๋ถ€์—์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ• ์ˆ˜ ์—†๋‹ค. ์ด๋Ÿฐ ์•„์ด๋””์–ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ƒ์„ฑ ์ž์ฒด์— ์ œํ•œ์„ ๊ฐ€ํ•ด ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿผ ์ฒ˜์Œ์— ๋งํ•œ ํ”„๋ฆฐํ„ฐ์˜ ์˜ˆ์ œ๋ฅผ ์œ„์˜ ์•„์ด๋””์–ด๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด์ž.

~cpp 
class PrintJob;     // ๋ฏธ๋ฆฌ ์„ ์–ธ, ํ”„๋ฆฐํ„ฐ ์ž‘์—…์— ์“ฐ์ด๋Š” ๊ฐ์ฒด. ์ฐธ๊ณ  Effective C++ Item 34
class Printer {
public:
    void submitJob(const PrintJob& job);
    void reset();
    void performSelfTest();
    ...
    friend Printer& thePrinter();   // ์ด friend ํ•จ์ˆ˜๊ฐ€ ์œ ์ผํ•œ ๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ์œ ์ง€ ์‹œํ‚ค๊ณ 
                                    // ๊ฐ์ฒด์˜ ์‚ฌ์šฉ๊ถŒํ•œ์„ ๋ถ€์—ฌ ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
private:
    Printer();
    Printer(const Printer& rhs);
    ...
};
Printer& thePrinter()
{
    static Printer p;               // ๋‹จ์ผ์˜ Printer ๊ฐ์ฒด(the single printer object)
    return p;
}    
ํ•ด๋‹น ๋””์ž์ธ์€ ์„ธ๊ฐ€์ง€์˜ ์ค‘์ ์œผ๋กœ ์ดํ•ด ํ•˜๋ฉด ๋œ๋‹ค. ์ฒซ๋ฒˆ์งธ Printerํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž๋ฅผ private(์‚ฌ์—ญ)์ธ์ž๋กœ ์„ค์ •ํ•œ๋‹ค. ์ด๋Š” ๊ฐ์ฒด ์ƒ์„ฑ์„ ์ œํ•œํ•œ๋‹ค. ๋‘๋ฒˆ์งธ ์ „์—ญ ํ•จ์ˆ˜์ธ thePrinter๋ฅผ Printerํด๋ž˜์Šค์˜ friend๋กœ ์„ ์–ธํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์ด thePrinter๊ฐ€ ์ฒซ๋ฒˆ์งธ์—์„œ์˜ ์ œํ•œ์— ์ƒ๊ด€์—†์ด ๊ด€์—ฌ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“ ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ(์„ธ๋ฒˆ์งธ) ์ „์—ญํ•จ์ˆ˜์ธ thePrinter ๋‚ด๋ถ€์— ์ •์ (static) Printer ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค. ์ด๋Š” ์˜ค์ง ํ•˜๋‚˜๋งŒ์˜ ๊ฐ์ฒด๋ฅผ thePrinter๋‚ด๋ถ€์— ์œ ์ง€์‹œํ‚จ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ์ž…์žฅ์—์„œ๋Š” ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

~cpp 
class PrintJob {
public:
  PrintJob(const string& whatToPrint);
  ...

};
string buffer;

...                              // ๋ฒ„ํผ์˜ ์ธ์ž๋ฅผ ๋„ฃ๋Š” ์ฝ”๋“œ

thePrinter().reset();
thePrinter().submitJob(buffer);  // ์ƒ์ˆ˜ ์ฐธ์กฐ(const reference)๋ผ์„œ, 
                                 // ์ž„์‹œ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜์–ด ์‹คํ–‰๋œ๋‹ค.
ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„์‹œ์—๋Š” thePrinter๊ฐ€ "์ „์—ญ ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค." ๊ฒƒ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์•ฝํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค. ์•Œ๋‹ค ์‹œํ”ผ, ์ „์—ญ ๊ณต๊ฐ„์˜ ์‚ฌ์šฉ์€ ๋˜๋„๋ก์ด๋ฉด ํ”ผํ•ด์•ผ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ฉฐ, thePrinter๋ฅผ Printerํด๋ž˜์Šค ๋‚ด๋ถ€์— ์ˆจ๊ธฐ๊ธฐ๋ฅผ ์ถ”์ฒœํ•˜๋‹ค. thePrinter๋ฅผ Printerํด๋ž˜์Šค ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ๋กœ ๋„ฃ์–ด ๋ฒ„๋ฆฌ๊ณ , friend๋ฅผ ์‚ญ์ œํ•ด ๋ณด์ž.

~cpp 
class Printer {
public:
  static Printer& thePrinter();     // ์™ธ๋ถ€์—์„œ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•˜๋„๋ก static์œผ๋กœ ์„ ์–ธํ•˜๊ณ 
  ...

private:
  Printer();
  Printer(const Printer& rhs);
  ...

};

Printer& Printer::thePrinter()      // friend๋งŒ ์—†์•ด์ง€ ๋งˆ์ฐฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์ œ์‹œํ•œ๋‹ค.
{
  static Printer p;
  return p;
}
๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๊ฒ ๋‹ค.

~cpp 
Printer::thePrinter().reset();
Printer::thePrinter().submitJob(buffer);
์ „์—ญ ๊ณต๊ฐ„ ์‚ฌ์šฉ์— ๋Œ€ํ•œ ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ์ฑ…์˜ ๋˜๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ํ•œ๋‹ค๋ฉด, name space๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‹จ์ˆœํžˆ PrintingStuff name space๋กœ ๋ฌถ์–ด ๋ฒ„๋ฆฐ๋‹ค.

~cpp 
namespace PrintingStuff {                    // namespace์˜ ์‹œ์ž‘
  class Printer {                            // namespace๋กœ์„œ ์ด ํด๋ž˜์Šค๋Š” 
  public:                                    // PrintingStuff namespace ์•ˆ์— ์กด์žฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

    void submitJob(const PrintJob& job);
    void reset();
    void performSelfTest();
    ...
    friend Printer& thePrinter();
  private:
    Printer();
    Printer(const Printer& rhs);
    ...
 };
 Printer& thePrinter()                        // ์ด friend ํ•จ์ˆ˜ ์—ญ์‹œ ์ „์—ญ์ด ์•„๋‹Œ 
 {                                            // PrintingStuff namespace์•ˆ์— ์กด์žฌ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
    static Printer p;
    return p;
 }
}                                             // namespace์˜ ๋
๊ทธ๋ฆฌ๊ณ  thePrinter๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๋ฉด ์ด์ œ๋Š” ์ด๋ ‡๊ฒŒ ํ•ด์•ผ ํ•œ๋‹ค.

~cpp 
PrintingStuff::thePrinter().reset();
PrintingStuff::thePrinter().submitJob(buffer);
๋ฌผ๋ก  using ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•ด๋‹น ์ด๋ฆ„์„ ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉํ• ์ˆ˜ ์ž‡๋‹ค.

~cpp 
using PrintingStuff::thePrinter;    // thePrinter๋ฅผ ํ˜„์žฌ์˜ namespace์•ˆ์—์„œ 
                                    // ์ž์œ ๋กœ์ด ์“ธ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ ๋‹ค.                                            
thePrinter().reset();               // ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๊ณผ์ •
thePrinter().submitJob(buffer);
thePrinter ๋ฅผ ์ ์šฉํ• ๋•Œ ๋‘๊ฐ€์ง€ ์ƒ๊ฐํ•ด์•ผํ•  ๋ฏธ๋ฌ˜ํ•œ ๋ฌธ์ œ์ ์ด ์žˆ๋‹ค.

์ฒซ๋ฒˆ์งธ๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฐ์ฒด์˜ ์œ„์น˜์ด๋‹ค. ์œ„์˜ ์ œ์‹œ๋œ ๋‘๊ฐ€์ง€์˜ ๋ฐฉ๋ฒ•์—์„œ, Printer ์ •์ (staitc) ๊ฐ์ฒด๊ฐ€ ํ•˜๋‚˜๋Š” friend๋กœ ํด๋ž˜์Šค์˜ ์ œ์–ด๊ถŒ์„ ํš๋“ํ•œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์žˆ๊ณ , ๋˜ ํ•˜๋‚˜๋Š” ํด๋ž˜์Šค ๋ฉค๋ฒ„ ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€์— ์žˆ๋‹ค. ํ•จ์ˆ˜์— ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ์ •์ (static) ๊ฐ์ฒด๋Š” ํ•ญ์ƒ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋‹ค. ์ด ์˜๋ฏธ๋Š” ํ•ด๋‹น ์ฝ”๋“œ์˜ ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘๋ ๋•Œ ๋ถ€ํ„ฐ ์•„์˜ˆ ๊ฐ์ฒด๊ฐ€ ๋งŒ๋“ค์–ด ์ง„๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ์ฆ‰, ํ•œ๋ฒˆ๋„ ๊ทธ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„, ๊ฐ์ฒด๋Š” ์ด๋ฏธ ๋งŒ๋“ค์–ด์ ธ ๋น„์šฉ์„ ์ง€์ถœํ•˜๊ฒŒ ํ•œ๋‹ค. ๋ฐ˜๋ฉด์—, ํ•จ์ˆ˜ ๋ฉค๋ฒ„ ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€์— ์ •์ (static)๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ํ›„์ž์˜ ๊ฒฝ์šฐ์—๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ์—ญํ• ์„ ํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ธ Printer::thePrinter ๊ฐ€ ์ œ์ผ ์ฒ˜์Œ ํ˜ธ์ถœ๋ ๋•Œ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. ์ด๊ฒƒ์€ C++์—์„œ "์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋น„์šฉ์€ ์ง€๋ถˆํ•˜์ง€ ์•Š๋Š”๋‹ค."์˜ ์„ค๊ณ„ ๋‹ค์†Œ ๋ณต์žกํ•œ ์ด๋…์— ๊ทผ๊ฐ„์„ ๋‘” ๊ฐœ๋…์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌํ•œ ๋ณต์žกํ•œ ๊ฐœ๋…์€ ๋‹น์‹ ์„ ํ•ด๊น”๋ฆฌ๊ฒŒ ๋งŒ๋“ ๋‹ค.

( DeleteMe Translation unit์˜ ํ•ด์„์ด ๋ถˆ๋ถ„๋ช…ํ•˜๋‹ค.)
๋˜ ์ด ๋‘˜์˜ ๋‹ค๋ฅธ ์ทจ์•ฝ์ ์€ ์ดˆ๊ธฐํ™” ๋˜๋Š” ์‹œ๊ฐ„์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ํ•จ์ˆ˜์˜ ๊ฒฝ์šฐ์— ์ดˆ๊ธฐํ™” ์‹œ๊ฐ„์„ ์ •ํ™•ํžˆ ์•Œ์ˆ˜ ์žˆ๋‹ค. ์•„์˜ˆ ์ฒ˜์Œ ์ด๋‹ˆ๊นŒ ํ•˜์ง€๋งŒ ๋ฉค๋ฒ„ ๋ฉ”์†Œ๋“œ๋กœ ๊ตฌํ˜„์‹œ์—๋Š” ๋ชจํ˜ธํ•˜๋‹ค. C++๋Š” ํ™•์‹คํžˆ ํŠน๋ณ„ํ•˜๊ฒŒ ํ•ด์„ํ•ด์•ผ ํ•  ๋ถ€๋ถ„(๋‹จ์ผ ๊ฐ์ฒด์—์„œ ์†Œ์Šค ์ฝ”๋“œ ๋ชธ์ฒด ๋ถ€๋ถ„ ๋”ฐ์œ„)์€ ์ •์  ์ธ์ž๋“ค์— ๋Œ€ํ•œ ์ดˆ๊ธฐํ™” ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์„œ๋กœ ๋‹ค๋ฅธ ํ•ด์„ ๋ถ€๋ถ„(translation unit)์— ์žˆ๋Š” ์ •์  ๊ฐ์ฒด๋“ค์˜ ์ดˆ๊ธฐํ™” ์ˆœ์„œ์— ๋Œ€ํ•ด์„œ๋Š” ๋งํ• ์ˆ˜๊ฐ€ ์—†๋‹ค. ์ด๊ฒƒ์€ ๋จธ๋ฆฌ๋ฅผ ์•„ํ”„๊ฒŒ๋งŒ ํ• ๋ฟ์ด๋‹ค.

๋‘๋ฒˆ์งธ๋กœ ๋ฏธ๋ฌ˜ํ•œ ๋ฌธ์ œ๋ผ๋ฉด, inline๊ณผ ์ •์  ๊ฐ์ฒด์˜ ๊ด€๊ฒŒ์ด๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋น„๋ฉค๋ฒ„ ๋ฒ„์ „์˜ thePrinter๋ฅผ ๋ณด๋ฉด

~cpp 
Printer& thePrinter()
{
    static Printer p;
    return p;
}
๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ์˜ ํ•จ์ˆ˜๋Š” ๋งค์šฐ ์งง๋‹ค. ์ด๋Ÿฐ ์งง์€ ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜๋ณด๋‹ค inline ์‹œ์ผœ์„œ ์†๋„๋ฅผ ๋†’์ด๋Š” ๊ฒƒ์ด ๋” ํšจ๊ณผ์ ์ด๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋Ÿด์ˆ˜๊ฐ€ ์—†๋‹ค. ์™œ ๊ทธ๋Ÿฐ๊ฐ€ ํ•˜๋ฉด, inline์˜ ์˜๋ฏธ๋Š” ์ •ํ™•ํžˆ ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ์“ฐ์ด๋Š” ์ฝ”๋“œ๋ฅผ ํ˜„์žฌ ํ•จ์ˆ˜์˜ ๋ชธ์ฒด๋กœ ๊ต์ฒดํ•ด ๋ฒ„๋ฆฌ๋Š” ์—ญํ• ์ด๋‹ค. ๊ทธ๋Ÿฐ๊ฒŒ ์ด๋ ‡๊ฒŒ ํ• ๊ฒฝ์šฐ, ์œ„์™€ ๊ฐ™์€ ํ•จ์ˆ˜๋Š” static๊ฐ์ฒด์˜ ์ฒ˜๋ฆฌ์—์„œ ์˜๋ฌธ์ด ์ƒ๊ธด๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ ๊ณณ์„ ์œ„์™€ ๊ฐ™์€ ํ•จ์ˆ˜ ๋ชธ์ฒด๋กœ ๊ต์ฒดํ•˜๋ฉด, ๊ฐ ๊ต์ฒด ๋ถ€๋ถ„์€ ์ „๋ถ€ ๋…๋ฆฝ์ ์ธ static ์ธ์ž๋ฅผ ๋ถ€์—ฌ ๋ฐ›๋Š” ์…ˆ์ด ๋˜์–ด ๋ฒ„๋ฆฐ๋‹ค. ๊ทธ๋ž˜์„œ ์ •์  ์ธ์ž๋ฅผ ์“ด ํ•จ์ˆ˜๋Š” inline์„ ์‹œํ‚ค์ง€ ๋ชปํ•˜๋ฉฐ, ์ด๋Ÿฐ ์ •์  ์ธ์ž์˜ ์‚ฌ์šฉ์— ๋”ฐ๋ผ ์ผ์–ด๋‚˜๋Š” ์˜๋ฌธ์„ internal linkage๋ฅผ ๊ฐ€์ง„ ๋ฌธ์ œ ๋ผ๊ณ  ํ•œ๋‹ค. DeleteMe) ๋‚ ๋ฆผ ์š”์•ฝ ์ˆ˜์ • ํ•„์š”

์ž, ๋˜‘๋˜‘ํ•œ ์‚ฌ๋žŒ ์ด๋ผ๋ฉด ๋‹น์—ฐํžˆ, ์ง€๊ธˆ๊นŒ์ง€์˜ ์ฝ”๋“œ์—์„œ ์˜๋ฌธ์ ๊ณผ ๋ฌธ๋ฒ•์— ๋Œ€ํ•œ ์˜์•„ํ•จ์„ ์ผ์œผ ํ‚ฌ์ˆ˜ ์žˆ๋‹ค. thePrinter๋Š” ๋‘˜๋‹ค ๋‚ด๋ถ€์— ์žˆ๋Š” static ๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ, ์ด "static ๊ฐ์ฒด๋Š” ํ•ด๋‹น ํ•จ์ˆ˜,๋ฉ”์†Œ๋“œ์˜ ์˜์—ญ(scop) ๋‚ด๋ถ€์—์„œ ์“ฐ์—ฌ์•ผ์ง€ ์™ธ๋ถ€์—์„œ ์“ฐ์ด๋ฉด ์•ˆ๋˜์ง€ ์•Š๋Š”๊ฐ€?" ๋ผ๋Š” ์˜๋ฌธ์ด ๊ทธ๊ฒƒ์ด๋‹ค. ์ฆ‰, ํด๋ผ์ด์–ธํŠธ ์ž…์žฅ์—์„œ ์ด๋“ค ๊ฐ์ฒด๋Š” ์ˆจ๊ฒจ์ ธ(hidden)์žˆ๋Š” ์กด์žฌ์ด๊ณ , ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ž˜๋ชป๋œ ๋ฐฉ๋ฒ•์ด๋‹ค. ๋ผ๊ณ  ๋งํ• ์ˆ˜ ์žˆ๊ฒ ๋Š”๋ฐ, ๊ทธ๋ž˜์„œ ์•„๋งˆ ๋‹น์‹ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ์ฒด์˜ ์ˆซ์ž๋ฅผ ์„ธ๊ณ , ์ œํ•œ๋œ ๊ฐ์ฒด์˜ ์ˆ˜๋ณด๋‹ค ๋” ๋งŽ์€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉ์‹œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ ๋งํ•  ๊ฒƒ์ด๋‹ค.

~cpp 
class Printer {
public:
  class TooManyObjects{};                   // ๋„ˆ๋ฌด ๋งŽ์€ ๊ฐ์ฒด๋ฅผ ์š”๊ตฌํ•˜๋ฉด 
                                            // ์ด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ ์‹œํ‚จ๋‹ค.
  Printer();
  ~Printer();
  ...
private:
  static size_t numObjects;

  Printer(const Printer& rhs);               // ํ”„๋ฆฐํ„ฐ๋Š” 1๊ฐœ๋งŒ ํ—ˆ์šฉํ•˜๋ฉฐ, ์‚ฌ๋ณธ๋„ ํ—ˆ์šฉ ํ•˜์ง€
                                             // ์•Š๋Š”๋‹ค. Item E27
};                                           
์ด๋Ÿฐ ์•„์ด๋””์–ด๋Š” numObject๋ฅผ ์‚ฌ์šฉํ•ด์„œ Printer๊ฐ์ฒด์˜ ์ˆ˜๋ฅผ ์ œํ•œ ์‹œ์ผœ ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค. ์œ„์—๋„ ์–ธ๊ธ‰ํ•˜์˜€๋“ฏ์ด ๊ฐ์ฒด์˜ ์ˆ˜๊ฐ€ 1๊ฐœ๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด, TooManyObject ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

~cpp 
size_t Printer::numObjects = 0;             

Printer::Printer()
{
    if (numObjects >= 1) {
        throw TooManyObjects();
    }
    ๋ณดํ†ต์˜ ์ƒ์„ฑ ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    ++numObjects;
}

Printer::~Printer()
{
    ๋ณดํ†ต์˜ ํŒŒ๊ดด ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    --numObjects;
}
์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๋ฐฉ๋ฒ•์€ ๋งค๋ ฅ์ ์ด๋ฉฐ, ๋‹จ์ง€ ๊ฐ์ฒด์˜ ์ˆ˜๋ฅผ 1๊ฐœ์— ๊ตญํ•œ ํ•˜์ง€ ์•Š๊ณ , ํŠน์ • ์ˆซ์ž๋กœ ์กฐ์ •ํ• ์ˆ˜ ์žˆ๋Š” ์ด์ ์ด ์žˆ๋‹ค. ์‚ฌ์šฉํ•˜๊ธฐ๋Š” ๊ท€์ฐฎ์•„๋„ ๋ง์ด๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ฒƒ์˜ ๋ฌธ์ œ๋ฅผ ๋ฐ”๋กœ ๋‹ค๋ฃจ์–ด ์ฃผ๊ฒ ๋‹ค.

1.2.2. Context for Object Construction : ๊ฐ์ฒด์˜ ์ƒ์„ฑ์„ ์œ„ํ•œ ๊ตฌ๋ฌธ(๊ด€๊ณ„, ๋ฌธ๋งฅ, ์ƒํ™ฉ)

๋ฐฉ๊ธˆ ์œ„์—์„œ ์˜ˆ์ œ๋กœ ์ œ์‹œํ•œ ๋ฐฉ๋ฒ• ์—ญ์‹œ ๋ฌธ์ œ๋Š” ๋‚ดํฌํ•˜๊ณ  ์žˆ๋‹ค. ๊ฐ€๋ น ํŠน๋ณ„ํ•œ ํ”„๋ฆฐํ„ฐ์ธ ์ปฌ๋Ÿฌ ํ”„๋ฆฐํ„ฐ์— ๋Œ€ํ•œ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณธ๋‹ค.

~cpp 
class ColorPrinter: public Printer {
  ...
};
๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด์ž.

~cpp 
Printer p;
ColorPrinter cp;

์ฒซ๋ฒˆ์งธ ๊ฐ์ฒด p๋Š” ์ˆœ์กฐ๋กœํžˆ ์ƒ์„ฑ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์—„์—ฐํžˆ ๋‹ค๋ฅธ ํ”„๋ฆฐํ„ฐ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•˜๊ณ  ์žˆ๋Š” cp๋Š” ์ƒ์„ฑ๋˜์ง€ ์•Š๊ณ , TooManyObjects ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ ์‹œํ‚จ๋‹ค. ์™œ ๊ทธ๋Ÿฌ๋Š”์ง€ ๋ชจ๋‘๋“ค ์˜ˆ์ƒ ํ• ๊ฒƒ์ด๋‹ค. ๋”๋ถˆ์–ด ๋น„์Šท ๋˜ ๋‹ค๋ฅธ ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐ ํ•ด ๋ณธ๋‹ค๋ฉด.

~cpp 
class CPFMachine {                           // copy, print, fax ์ „๋ถ€ ํ• ์ˆ˜ ์žˆ๋Š” ๊ธฐ๊ณ„
private:                                     
  Printer p;                                 // ํ”„๋ฆฌํ„ฐ ๊ธฐ๋Šฅ์˜ ์ธ์ž.
  FaxMachine f;                              // ํŒฉ์Šค ๊ธฐ๋Šฅ์˜ ์ธ์ž
  CopyMachine c;                             // ๋ณต์‚ฌ๊ธฐ ๊ธฐ๋Šฅ์˜ ์ธ์ž.

  ...

};

CPFMachine m1;                               // ์—ฌ๊ธฐ ๊นŒ์ง€๋Š” ์ž˜๋œ๋‹ค.

CPFMachine m2;                               // TooManyObjects ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ ์‹œํ‚จ๋‹ค.

Printer ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ• ์ˆ˜ ์žˆ๋Š” ์„ธ๊ฐ€์ง€์˜ ์ƒํ™ฉ์—์„œ ์ด๋Ÿฐ ๋ฌธ์ œ๋Š” ๋ฐœ์ƒ ๋ ์ˆ˜ ์žˆ๋‹ค. : ๊ทธ๋ƒฅ ๊ทธ๋“ค ์ž์ฒด๋ฅผ ์„ ์–ธํ•ด์„œ ์‚ฌ์šฉํ•˜๊ธฐ. ๋‹ค๋ฅธ ํด๋ž˜์Šค๋กœ ์œ ๋„๋ ๋•Œ. ์ข€๋” ํฐ ํด๋ž˜์Šค์—์„œ ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ธ์ž๋กœ ํฌ์šฉํ• ๋•Œ ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ˆซ์ž๋กœ ์ œ์–ดํ•˜๊ณ , ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹Œ ์ƒ์„ฑ์ž๊ฐ€ ์‚ฌ์—ญ(private)์ธ์ž๋กœ ๋“ค์–ด๊ฐ„ ๊ฒฝ์šฐ์—๋Š” ํ•ด๋‹น ํด๋ž˜์Šค์—์„œ ์œ ๋„๋œ ํด๋ž˜์Šค๋“ค๋„ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ•˜๋ฉฐ, ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์ธ์ž๋กœ๋„ ๋“ค์–ด๊ฐˆ์ˆ˜๊ฐ€ ์—†์–ด์„œ, ์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์ด ๋ด‰์‡„๋œ๋‹ค.

์ž, ์ด๋Ÿฐ๊ฑธ๋กœ ํ•œ๊ฐ€์ง€ ์žฌ๋ฏธ์žˆ๋Š” ๊ฒƒ์„ ๋งŒ๋“ค์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ๋‹น์‹ ์ด C++์ƒ์—์„œ ๋”์ด์ƒ ์ƒ์† ๋˜์ง€ ์•Š๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์„๋•Œ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ?(์ฃผ:์ฐธ๊ณ ๋กœ Java๋‚˜ C#์˜ ๊ฒฝ์šฐ ์–ธ์–ด ์„ค๊ณ„ ๋•Œ๋ถ€ํ„ฐ ์•„์˜ˆ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰์„ ์œ„ํ•œ ํ‚ค์›Œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ํ•˜์ง€๋งŒ C++๋Š” ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์„ ์„ค๊ณ„์ž๊ฐ€ ์ƒ๊ฐํ•œ๊ฑด์ง€, ์ฐจํ›„ C++์˜ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ƒ๊ฐํ•œ๊ฑด์ง€ ๋†€๋ผ์šธ ๋ฟ์ด๋‹ค. ๋ฐ”๋กœ ์ด์ „์— ๋‚˜์˜จ ๊ฐ€์ƒ ๋ณต์‚ฌ ์ƒ์„ฑ์ž์˜ ์•„์ด๋””์–ด์™€ ๋น„์Šทํ•˜๋‹ค๊ณ  ํ•ด์•ผ ํ• ๊นŒ)

~cpp 
class FSA {
public:
  // ๊ฐ€์งœ ์ƒ์„ฑ์ž๋“ค
  static FSA * makeFSA();   // ์ƒ์„ฑ์ž
  static FSA * makeFSA(const FSA& rhs); // ๋ณต์‚ฌ ์ƒ์„ฑ์ž
  ...

private:
  FSA();
  FSA(const FSA& rhs);
  ...
};

FSA * FSA::makeFSA()
{ return new FSA(); }

FSA * FSA::makeFSA(const FSA& rhs)
{ return new FSA(rhs); }
์ด๋ ‡๊ฒŒ ์ƒ์„ฑ์ž๊ฐ€ ์‚ฌ์—ญ(private)์ธ์ž๋กœ ๋“ค์–ด๊ฐ€ ๋ฒ„๋ฆฌ๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค์—์„œ ์œ ๋„๋˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ๋ž€ ๋ถˆ๊ฐ€๋Šฅ ํ•˜๋‹ค. ํ•˜์ง€๋งŒ ์ด ์ฝ”๋“œ์˜ ๋ฌธ์ œ์ ์€ makeFSA๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑํ•˜๋ฉด ํ•ญ์ƒ delete๋ฅผ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ์ด์ „ ์˜ˆ์™ธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ถ€๋ถ„์—์„œ๋„ ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ, ์ด๋Š” ์ž์›์ด ์„ธ๋‚˜๊ฐˆ ์—ฌ์ง€๋ฅผ ๋‚จ๊ธฐ๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ฅผ ์œ„ํ•œ STL์˜ auto_ptr๋„ ์ฐธ๊ณ ํ•˜์ž.(Item 9 ์ฐธ๊ณ )

~cpp 
// ๊ธฐ๋ณธ ์ƒ์„ฑ์ž
auto_ptr<FSA> pfsa1(FSA::makeFSA());

// ๋ณต์‚ฌ ์ƒ์„ฑ์ž
auto_ptr<FSA> pfsa2(FSA::makeFSA(*pfsa1));

...                            // ์ž ์ด์ œ ํ•ด๋‹น ์˜์—ญ์„ ๋ฒ—์–ด๋‚˜๋ฉด ๊ฐ์ฒด๋Š” ์ž๋™ ํŒŒ๊ดด๋œ๋‹ค.

1.2.3. Allowing Objects to Come and Go : ๊ฐ์ฒด๊ฐ€ ์˜ค๊ณ  ๊ฐ์„ ํ—ˆ์šฉํ•˜๊ธฐ?

์ด์ œ, ๋‹จ์ผํ•œ ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ ๋ฐฉ๋ฒ•์— ๊ด€ํ•œ ๋””์ž์ธ ๋ฐฉ๋ฒ•์€ ์•Œ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ , ๊ฐ์ฒด๋ฅผ ์ˆซ์ž๋กœ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์€ ์„ธ๊ฐ€์ง€์˜ ์ƒ์„ฑ ์ƒํ™ฉ์— ์˜ํ•ด์„œ ํญ์žกํ•œ ์ƒํ™ฉ์„ ๋งŒ๋“ค์–ด ๋‚˜๊ฐ„๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์„ ์œ„ํ•ด์„œ ์ƒ์„ฑ์ž์˜ ์‚ฌ์—ญ(private)์—ญ์‹œ ์„ค๋ช…ํ–ˆ๋‹ค. ์บก์Аํ™”๋œ thePrinterํ•จ์ˆ˜๋Š” Printer๋ผ๋Š” ๋‹จ์ผํ•œ ๊ฐ์ฒด๋ฅผ ์ œํ•œํ•˜๊ณ , ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค. thePrinter๊ฐ€ ๋Œ€์•ˆ์ผ๊นŒ. ํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ thePrinter๋Š” C++์˜ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ธ ์ด๋Ÿฌํ•œ ๋””์ž์ธ์˜ ์ฝ”๋“œ๋ฅผ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค.

~cpp 
create Printer object p1;

use p1;

destroy p1;

create Printer object p2;

use p2;

destroy p2;
์ด๋Ÿฐ ๋””์ž์ธ์€ ๋‹จ์ผ Printer๊ฐ์ฒด์— ๊ด€ํ•ด์„œ ํ–‰ํ•˜์—ฌ ์งˆ์ˆ˜๋Š” ์—†๋‹ค. ํ•˜์ง€๋งŒ ์„œ๋กœ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๋ถ€๋ถ„์—์„œ Printer๊ฐ์ฒด๋Š” ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉ๋˜์–ด ์งˆ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ ์—ญ์‹œ ํ—ˆ์šฉํ•˜์ง€ ๋ชปํ•˜๊ฒŒํ•˜๋Š” ๊ฒƒ๊นŒ์ง€๋Š” ํ•„์š” ์—†์„๊ฒƒ ๊ฐ™์€๋ฐ, ์•„๋ฌดํŠผ ์˜ค์ง ํ•˜๋‚˜์˜ ํ”„๋ฆฐํ„ฐ ๊ฐ์ฒด๋งŒ ์œ ์ง€ ์‹œํ‚จ๋‹ค๋Š” ๊ฒƒ์—๋Š” ๋ฒ—์–ด๋‚˜์ง€๋Š” ์•Š๋Š” ๊ฑฐ๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์— ์šฐ๋ฆฌ๊ฐ€ ํ•ด์™”๋˜ object-counting๋ฐฉ๋ฒ•๊ณผ, ์ผ์ฐ์ด ์“ด ๊ฐ€์งœ ์ƒ์„ฑ์ž(pseudo-constructor)๋ฅผ ํ˜ผํ•ฉํ•ด์„œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด ๋ณธ๋‹ค.

~cpp 
class Printer {
public:
    class TooManyObjects{};

    static Printer * makePrinter();        // ๊ฐ€์งœ ์ƒ์„ฑ์ž(pseudo-constructors)

    ~Printer();
    void submitJob(const PrintJob& job);
    void reset();
    void performSelfTest();
    ...

private:
    static size_t numObjects;
    Printer();
    Printer(const Printer& rhs);         // ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๋Š” ๋ณต์‚ฌ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด
                                         // ๊ตฌํ˜„ ๋˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค. ( E27์ฐธ๊ณ )  DeleteMe)๊ฒ€์ฆํ•„์š”
};
// ํด๋ž˜์Šค์˜ static์˜ ์ •์˜(definition,๋น„์Šทํ•˜๊ฒŒ ์ดˆ๊ธฐ๊ฐ’ ๊ตฌํ˜„)์€ ๋ฐ˜๋“œ์‹œ ํ•ด์•ผ ํ•œ๋‹ค.
size_t Printer::numObjects = 0;
Printer::Printer()
{
    if (numObjects >= 1) {
        throw TooManyObjects();
    }
    ๋ณดํ†ต์˜ ์ƒ์„ฑ ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    ++numObjects;
}
Printer * Printer::makePrinter()
{ return new Printer; }
๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋Š” ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ๋งŒ ํ•œ๋‹ค.

~cpp 
Printer p1;               // ์ƒ์„ฑ์ž๊ฐ€ ์‚ฌ์—ญ(private)์ด๋ฏ€๋กœ
                          // ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ ์‹œํ‚จ๋‹ค.

Printer *p2 =  Printer::makePrinter();      // ์˜ฌ๋ฐ”๋ฅด๋‹ค. ์ด๊ฒƒ์ด ๊ธฐ๋ณธ ์ƒ์„ฑ์ž์ด๋‹ค.

Printer p3 = *p2;                           // ์—๋Ÿฌ! ๋ณต์‚ฌ ์ƒ์„ฑ์ž ์—ญ์‹œ ์‚ฌ์—ญ์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋‹ค.

p2->performSelfTest();                      // ๊ฐ์ฒด ์‚ฌ์šฉํ•˜๋“ฏ์ด ํ•œ๋‹ค.
p2->reset();                                // ๋งˆ์ฐฌ๊ฐ€์ง€
...
delete p2;                                  // ์ž์›์ด ์„ธ๋‚˜๊ฐ€์ง€ ์•Š๊ธฐ์œ„ํ•ด ์ œ๊ฑฐ ํ•ด์ค€๋‹ค.
                                            // auto_ptr์„ ์“ฐ๋ฉด ์ด๋„ ํ•„์š” ์—†์–ด ์ง„๋‹ค.
์ด๋Ÿฌํ•œ ๊ธฐ์ˆ ์€ ์–ด๋– ํ•œ ์ˆซ์ž์˜ ๊ฐ์ฒด์˜ ์ œํ•œ์—๋„ ์จ๋จน์„์ˆ˜ ์žˆ๋Š”๋ฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋”ฉ์œผ๋กœ ๊ฐ€๋Šฅํ•˜๋‹ค ๋‹ค์Œ์€ ๊ฐ์ฒด๋ฅผ 10๊ฐœ๋กœ ์ œํ•œ ์‹œ์ผœ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค.

~cpp 
class Printer {
public:
    class TooManyObjects{};
    static Printer * makePrinter();   // // ๊ฐ€์งœ ์ƒ์„ฑ์ž(pseudo-constructors)
    static Printer * makePrinter(const Printer& rhs);
    ...
private:
    static size_t numObjects;
    static const size_t maxObjects = 10;       // ์•„๋ž˜ ์ฐธ๊ณ 
    Printer();
    Printer(const Printer& rhs);
};
// ํด๋ž˜์Šค์˜ static์˜ ์ •์˜(definition,๋น„์Šทํ•˜๊ฒŒ ์ดˆ๊ธฐ๊ฐ’ ๊ตฌํ˜„)์€ ๋ฐ˜๋“œ์‹œ ํ•ด์•ผ ํ•œ๋‹ค.
size_t Printer::numObjects = 0;
const size_t Printer::maxObjects;

Printer::Printer()
{
    if (numObjects >= maxObjects) {
        throw TooManyObjects();
    }
    ...
}
Printer::Printer(const Printer& rhs)
{
    if (numObjects >= maxObjects) {
        throw TooManyObjects();
    }
    ...
}

Printer * Printer::makePrinter()
{ return new Printer; }

Printer * Printer::makePrinter(const Printer& rhs)
{ return new Printer(rhs); }
๊ฐ™์€ ์ฝ”๋“œ ์จ์„œ ๋‚ด์šฉ๋งŒ ๋Š˜๋ฆฐ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ ์กฐ๊ธˆ๋” ์–ธ๊ธ‰ํ•ด ๋ณธ๋‹ค๋ฉด. Printer::maxObjects๋Š” ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ 10์œผ๋กœ ์ดˆ๊ธฐํ™” ์‹œ์ผฐ๋Š”๋ฐ, ์ด๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์ง€์› ์—ฌ๋ถ€์— ๋”ฐ๋ผ static const ๋ฉค๋ฒ„์˜ ๊ฒฝ์šฐ ์ดˆ๊ธฐํ™”๊ฐ€ ๊ฐ€๋Šฅํ•œ C++์˜ ๊ทœ์น™์ด๋‹ค.(์ฃผ:์ฐธ๊ณ  ๋‚ด์šฉ์ด ์žˆ์—ˆ๋Š”๋ฐ ๋ช‡ ์žฅ์ธ์ง€ ๊ธฐ์–ต ์•ˆ๋‚œ๋‹ค.) ๊ทธ๋ฆฌ๊ณ  maxObject์— ๊ด€ํ•˜์—ฌ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฐ’์ด๊ธฐ์— enum์œผ๋กœ๋„ ์“ธ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

~cpp 
class Printer {
private:
    enum { maxObjects = 10 };      // ์œ„์˜ 10 ์ œํ•œ๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค.
};
๊ทธ๋ฆฌ๊ณ  ๋งŒ์•ฝ์— ํ˜„์žฌ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ ์ดˆ๊ธฐํ™”๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ์จ์„œ ํ•ด๊ฒฐํ•˜๋ผ.

~cpp 
class Printer {
private:
    static const size_t maxObjects;            // ์•„๋ฌด๋Ÿฐ ์ดˆ๊ธฐํ™”๋ฅผ ํ•˜์ง€ ์•Š๋Š”๋‹ค.
    ...

};
// ์—ฌ๊ธฐ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ดˆ๊ธฐํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
const size_t Printer::maxObjects = 10;
์œ„์˜ ๋‘˜๋‹ค ์ƒ๋‹จ์˜ ์ฝ”๋“œ์™€ ๋™์ผํ•œ ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ข‹์€ ์ปดํŒŒ์ผ๋Ÿฌ ์“ฐ์‹œ๊ธธ..

1.2.4. An Object-Counting Base Class : Object-counting์— ๊ธฐ๋ณธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋ณธ๋‹ค.

์ด์ œ๊นŒ์ง€ ๊ฑฐ์ณ์™”๋˜ ์ฝ”๋“œ๋“ค์€ ์–ด๋А ์ •๋„์˜ ํ˜•ํƒœ๊ฐ€ ์žกํ˜€ ์žˆ๋‹ค. ์ด๊ฒƒ์„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋งŒ๋“ค์–ด ๋†“๊ณ , ์ผ์ •ํ•œ ๊ทœ์น™์œผ๋กœ ๋งŒ๋“ค์ˆ˜๋Š” ์—†์„๊นŒ? (์ฐธ๊ณ ๋กœ ์ด์™€ ๋น„์Šทํ•œ ๊ธฐ์ˆ ์ด Item 29 reference-counting์— ๋“ฑ์žฅํ•œ๋‹ค. ์ฐธ๊ณ  ํ•ด๋ณด์ž.) template๊ฐ€ ์ด๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ค€๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ template๋ฅผ ์ด์šฉํ•ด์„œ

~cpp 
template<class BeingCounted>
class Counted {
public:
    class TooManyObjects{};        // ๋˜์งˆ ์˜ˆ์™ธ

    static int objectCount() { return numObjects; }

protected:
    Counted();
    Counted(const Counted& rhs);

    ~Counted() { --numObjects; }

private:
    static int numObjects;
    static const size_t maxObjects;

    void init();          // ์ƒ์„ฑ์ž์— ์ฝ”๋“œ ์ค‘๋ณต์„ ํ”ผํ•œ๋‹ค.(์–ด์ฐจํ”ผ ๊ฐ™์€ ์ฝ”๋“œ ์“ฐ๋‹ˆ๊นŒ.)
};                                            

template<class BeingCounted>
Counted<BeingCounted>::Counted()
{ init(); }

template<class BeingCounted>
Counted<BeingCounted>::Counted(const Counted<BeingCounted>&)
{ init(); }

template<class BeingCounted>
void Counted<BeingCounted>::init()
{
    if (numObjects >= maxObjects) throw TooManyObjects();
    ++numObjects;
}
ํ•ด๋‹น ํด๋ž˜์Šค๋Š” ์˜ค์ง ๊ธฐ๋ณธ ํด๋ž˜์Šค๋กœ๋งŒ ์“ฐ์ด๋„๋ก ์„ค๊ณ„๋˜์–ด ์กŒ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ, ์ƒ์„ฑ์ž์™€ ํŒŒ๊ดด์ž๊ฐ€ ๋ชจ๋‘ protected(๋ณดํ˜ธ)์ธ์ž๋กœ ์„ค์ •๋˜์–ด ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  init๋กœ์„œ object-counting์„ ๊ตฌํ˜„ํ•œ๋‹ค. init๋Š” ์„ค์ •๋œ ๊ฐ์ฒด์˜ ์ˆซ์ž๊ฐ€ ๋„˜์–ด๊ฐ€๋ฉด, TooManyObjects ์˜ˆ์™ธ ๊ฐ์ฒด๋ฅผ ๋ฐœ์ƒ ์‹œํ‚จ๋‹ค.

์ด์ œ ์œ„์˜ template๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ธ€ ์ดˆ๋ฐ˜์— ๋ˆ„๋ˆ„ํžˆ ์„ค๋ช…ํ•œ object-counting์— ๊ธฐ๋ฐ˜ํ•œ Printerํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋ณธ๋‹ค.

~cpp 
class Printer: private Counted<Printer> {
public:
    static Printer * makePrinter();     // ๊ฐ€์งœ ์ƒ์„ฑ์ž(pseudo-constructors)
    static Printer * makePrinter(const Printer& rhs);

    ~Printer();

    void submitJob(const PrintJob& job);
    void reset();
    void performSelfTest();
    ...

    using Counted<Printer>::objectCount;     // ์™œ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•„๋ž˜ ์ฐธ๊ณ 
    using Counted<Printer>::TooManyObjects;  // ๋งˆ์ฐฌ๊ฐ€์ง€~
private:
    Printer();
    Printer(const Printer& rhs);
};
์ดํ•ด๊ฐ€ ์•ˆ๊ฐ€๋Š” ๋ถ€๋ถ„์€ ์—ญ์‹œ๋‚˜ using์ด ์“ฐ์ธ ๊ณณ๊ณผ private๋กœ ์ƒ์† ๋˜์—ˆ๋‹ค๋Š” ์ ์ผ ๊ฒƒ์ด๋‹ค.

private๋ฅผ ๋จผ์ € ์„ค๋ช…ํ•ด ํ•œ๋‹ค. ๊ฒฐ๋ก ๋ถ€ํ„ฐ ์ด์•ผ๊ธฐํ•˜๋ฉด ์œ„ํ—˜์„ฑ ์ œ๊ฑฐ์™€, ํฌ๊ธฐ์˜ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด์„œ ์ด๋‹ค. ๋‹ค๋ฅธ ์ด๊ฐ€ Counted<Printer> ํฌ์ธํ„ฐ๋ฅผ ํ†ตํ•ด์„œ Printer๊ฐ์ฒด๋ฅผ ์ œ๊ฑฐํ•˜๋ ค๋Š” ์‹œ๋„๋ฅผ ํ• ์ง€๋„ ๋ชจ๋ฅธ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ , private์ƒ์†์€ Item 24์— ๋ช…๋ฐฑํžˆ ๋‚˜์™€ ์žˆ๋“ฏ์ด Counted๋‚ด์˜ ๊ฐ€์ƒ ํ•จ์ˆ˜๊ฐ€ ์กด์žฌ ํ•˜๋”๋ผ๋„, Printer์—์„œ ํ•ด๋‹น ๊ฐ€์ƒ ํ•จ์ˆ˜์— ๋Œ€ํ•œ vtbl์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ์„œ overhead๋ฅผ ์ค„์ธ๋‹ค.

using์„ ์จ์„œ Counted์— ์กด์žฌํ•˜๋Š” ์ธ์ž๋ฅผ ์ฐธ์กฐ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ์ด์œ ๋Š” Printer์ž…์žฅ์—์„œ ๋‹ค๋ฅธ ์ธ์ž๋“ค์€ ์‹ ๊ฒฝ ์“ธํ•„์š”๊ฐ€ ์—†์ง€๋งŒ, ๋ช‡๋ช‡ ํŠน์ •ํ•œ ์ธ์ž์˜ ์ฐธ์กฐ์™€, ์‚ฌ์šฉ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ด๋‹ค. objectCount๋Š” ์•„๋ž˜์˜ ์ฃผ์„๋ฌธ์˜ ์ด์œ ์ด๊ณ ,

~cpp 
class Printer: private Counted<Printer> {
public:
    ...
    using Counted<Printer>::objectCount;  // ์ด ํ•จ์ˆ˜๋กœ ํ˜„์žฌ ๊ฐ์ฒด์˜ ์ˆซ์ž๋ฅผ ์•Œ์ˆ˜ ์žˆ๋‹ค.
    ...                                   // ์ด๊ฑฐ ํ•จ์ˆ˜๋‹ค. ์ฐฉ๊ฐ ๋งˆ์‹œ๊ธธ. Counted ํด๋ž˜์Šค๋ฅผ ํ•œ๋ฒˆ ์‚ดํŽด๋ณด๋ผ.
};

๋งŒ์•ฝ, using์„ ์ง€์›ํ•˜์ง€ ์•Š์€ ์ปดํŒŒ์ผ๋Ÿฌ๋ผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜›๋‚  ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋‹ค.

~cpp 
class Printer: private Counted<Printer> {
public:
    ...
    Counted<Printer>::objectCount;  // ์ด ํ•จ์ˆ˜๋กœ ํ˜„์žฌ ๊ฐ์ฒด์˜ ์ˆซ์ž๋ฅผ ์•Œ์ˆ˜ ์žˆ๋‹ค.
    ...                                   // ์ด๊ฑฐ ํ•จ์ˆ˜๋‹ค. ์ฐฉ๊ฐ ๋งˆ์‹œ๊ธธ. Counted ํด๋ž˜์Šค๋ฅผ ํ•œ๋ฒˆ ์‚ดํŽด๋ณด๋ผ.
};
์ด๋Š” using์ด ์กด์žฌ ํ•˜์ง€ ์•Š์•˜์„๋•Œ ์‚ฌ์šฉ๋œ ์˜›๋‚  ๋ฌธ๋ฒ•์ด๋‹ค. TooManyObjects ํด๋ž˜์Šค ์—ญ์‹œ ๊ฐ™์€ ์ด์œ ๋กœ using์„ ์ด์šฉํ•ด์„œ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๊ถŒํ•œ์„ ์—ด์—ˆ์œผ๋ฉฐ, ์ด๋ ‡๊ฒŒ TooManyObjects๋ฅผ ํ—ˆ์šฉํ•ด์•ผ ์ง€๋งŒ ํ•ด์•ผ์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ๋“ค์ด ํ•ด๋‹น ์˜ˆ์™ธ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ๋‹ค.

์ƒ์„ฑ์ž์—์„œ ๊ฐ์•ˆํ•  ๊ฒƒ์€ ์—†๋‹ค. ๊ทธ๋ƒฅ ์ผ๋ฐ˜์ ์ธ ์ƒ์„ฑ๊ณผ์ •์„ ๊ธฐ์ˆ ํ•ด ์ฃผ๋ฉด ๋ฌด๋ฆฌ๊ฐ€ ์—†์œผ๋ฉฐ, ํ•„์š”ํ•œ ์ž‘์—…์€ Counted<Printer>์˜ ์ƒ์„ฑ์ž์—์„œ ํ•˜๊ธฐ๋•Œ๋ฌธ์— Printer์˜ ์ƒ์„ฑ์ž๋Š” ๋‹ค์Œ๊ณ  ๊ฐ™๋‹ค.

~cpp 
Printer::Printer()
{
    ์ผ๋ฐ˜์ ์ธ ์ƒ์„ฑ์ž ๊ณผ์ •
}
Printer์˜ ์ƒ์„ฑ์ž์—์„œ๋Š” ๊ฐ์ฒด๋ฅผ ์ ๊ฒ€ํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ๋“ค์–ด๊ฐ€์„œ๋Š” ์•ˆ๋œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด, Counted<Printer>์—์„œ ์ ๊ฒ€ํ•˜๊ณ  ์ด์ƒ ์žˆ์–ด์„œ ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค๋ฉด, ๋‹ค์Œ์— ๋ถˆ๋ฆด Printer์ƒ์„ฑ์ž๋Š” ์•„์˜ˆ ๋ถˆ๋ฆฌ์ง€๋„ ์•Š๋Š”๋‹ค. ์•Œ๊ฒ ๋‚˜?

๋˜ ํ•˜๋‚˜๋Š” object-counting์‹œ์— ์ดˆ๊ธฐ๊ฐ’์ด๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ดˆ๊ธฐํ™”๊ฐ€ ๋œ๋‹ค.

~cpp 
template<class BeingCounted>                 
int Counted<BeingCounted>::numObjects;  // ๊ฐ์ฒด์˜ ์„ ์–ธ๊ณผ, ์ž๋™์œผ๋กœ 0์œผ๋กœ ์ดˆ๊ธฐํ™”๊ฐ€ ๋œ๋‹ค.
DeleteMe) ์ด๊ฒƒ์ด ๋˜๋Š” ๊ณผ์ •๋„ ์ •ํ™•ํžˆ ์ดํ•ด๊ฐ€ ๊ฐ€์ง€ ์•Š๋Š”๋‹ค. ๋˜๋Š”๊ฑฐ์˜€๋‚˜ ์—ฌํƒœ? ๊ณ ๋ฏผ๋œ๋‹ค.

maxObjects์˜ ์ดˆ๊ธฐํ™” ์—ญ์‹œ ๋ฌธ์ œ๋กœ ๋Œ€๋‘ ๋˜๋Š”๋ฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ดˆ๊ธฐํ™” ์‹œํ‚จ๋‹ค.

~cpp 
const size_t Counted<Printer>::maxObjects = 10;
๋งŒ์•ฝ FileDescriptor๊ฐ€ ์œ ๋„๋œ ํด๋ž˜์Šค๋ผ๋ฉด ์ด๋ ‡๊ฒŒ ํ•œ๋‹ค.

~cpp 
const size_t Counted<FileDescriptor>::maxObjects = 16;
์ด๋Š” ๋น„๋ก ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ private๋กœ ์ƒ์† ๋ฐ›์•˜์ง€๋งŒ, ์œ ๋„๋œ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋ ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ดˆ๊ธฐํ™”๋ฅผ ์‹œํ‚ฌ์ˆ˜ ์žˆ๋‹ค. ์ดˆ๊ธฐํ™” ๋ฆฌ์ŠคํŠธ์™€ ๋น„์Šทํ•˜๋‹ค๊ณ  ํ•ด์•ผ ํ• ๊นŒ?

1.3. Item 27: Requiring or prohibiting heap-based objects.

  • Item 27: Heap์˜์—ญ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด ์š”๊ตฌํ•˜๊ธฐ or ํ”ผํ•˜๊ธฐ.

์ด๋ฒˆ ์žฅ์—์„œ๋Š” Heap์˜์—ญ์—์„œ ๊ฐ์ฒด ์‚ฌ์šฉ์— ๊ด€ํ•˜์—ฌ ๋‹ค๋ฃจ์–ด ๋ณธ๋‹ค.

๋•Œ๋กœ ์ž์‚ด์„ ํ—ˆ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๋•Œ๋„ ์žˆ๋‹ค. ํ‘œํ˜„์ด ๊ฒฉํ•œ๊ฐ€? "delete this"๋”ฐ์œ„ ๊ฐ™์ด ๋ง์ด๋‹ค. ์ด๋Ÿฌํ•œ ๊ฐ์ฒด๋Š” heap์˜์—ญ์— ๋ฐฐ์น˜ ๋˜๋Š”๋ฐ, ํ™•์‹คํ•˜๊ฒŒ ์ œ๊ฑฐ๋งŒ ํ•ด์ค€๋‹ค๋ฉด ์ž์›์ด ์…€ ์ด์œ ๋Š” ์—†๋‹ค. ๊ทธ๋ ‡๋‹ค. ์ฃผ์˜ ๊นŠ๊ฒŒ ๋‹ค๋ฃจ์–ด์•ผ ํ•˜๋Š” ๊ฐ์ฒด๋“ค์ด๋‹ค. embedded system๊ฐ™์ด ์—ด์•…ํ•œ ํ™˜๊ฒฝ์—์„œ ์ด๋“ค์— ์ž˜๋ชป๋‹ค๋ฃจ์–ด์„œ ์ผ์–ด๋‚œ ์‹ค์ˆ˜๋Š” ์น˜๋ช…์ ์ธ ์†์ƒ์„ ๋ถ€๋ฅธ๋‹ค. ์ด์ œ ํ•˜๋‚˜ํ•˜๋‚˜ heap์˜์—ญ์— ๊ด€๋ จํ•œ ๋‚ด์šฉ์„ ๋‹ค๋ฃฌ๋‹ค.

1.3.1. Requiring Heap-Based Objects : Heap ๊ธฐ๋ฐ˜ ๊ฐ์ฒด๋“ค์ด ํ•„์š”

์šฐ์„  ๊ฐ์ฒด๋ฅผ Heap์˜์—ญ ์ƒ์—์„œ๋งŒ ์ƒ์„ฑ๋˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด๋กœ ์ œํ•œํ•˜๋Š” ๊ฒƒ์— ๊ด€ํ•ด์„œ ์ƒ๊ฐํ•ด ๋ณด์ž. Heap์˜์—ญ์— ์ž๋ฆฌ๋ฅผ ์ฐจ์ง€ํ•˜๋Š” ๊ฐ์ฒด๋Š” ๋ชจ๋‘ new๋ฅผ ํ˜ธ์ถœํ•ด์„œ ํ•œ์ž๋ฆฌ์”ฉ ํ•˜๋‹ˆ, ๋ญ, ๊ฐ„๋‹จํžˆ new๋ฅผ ๋ง‰์•„ ๋ฒ„๋ฆฌ๋ฉด ๋˜๋Š”๊ฒƒ์ด๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๋ฐ˜๋Œ€๋กœ Heap์˜์—ญ์ด ์•„๋‹Œ ๊ฐ์ฒด๋“ค์€ ๋ชจ๋‘ new๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ , ์ž๋™์œผ๋กœ ๋ฌต์‹œ์  ์ƒ์„ฑ๋˜๊ณ , ๋ฌต์‹œ์  ํŒŒ๊ดด๋˜์–ด ์ง„๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ๋™ใ…†๋‹ค.

Item 26์— ๋‹ค๋ฃฌ๊ฒƒ๊ณผ ๊ฐ™์ด ์ƒ์„ฑ์ž์™€ ํŒŒ๊ดด์ž๋ฅผ ์‚ฌ์—ญ(private)๋กœ ๋ฌถ์–ด ๋ฒ„๋ฆฌ๋Š” ์•„์ด๋””์–ด๊ฐ€ ๊ฐ์ฒด ์ƒ์„ฑ ์ œํ•œ์˜ ์‹œ์ž‘์ด ๋ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ, ๋‘˜๋‹ค ๋ฌถ์–ด ๋ฒ„๋ฆฌ๋Š”๊ฑด ๋„ˆ๋ฌด ๊ณผ์ž‰์ด๋‹ค. ๊ทธ๋ƒฅ ํŒŒ๊ดด์ž๋งŒ์„ ์‚ฌ์—ญ(private)๋กœ ๋ฌถ์–ด ๋ฒ„๋ฆฌ๊ณ , ์ƒ์„ฑ์ž๋Š” ๊ณต์—ญ(public)์œผ๋กœ ๋†“์•„๋„ ํšจ๊ณผ๋Š” ๋น„์Šทํ•˜๋‹ค. ๋‹ค์Œ์˜ ์˜ˆ์ œ๋ฅผ ๋ณด์ž.

~cpp 
class UPNumber {
public:
    UPNumber();
    UPNumber(int initValue);
    UPNumber(double initValue);
    UPNumber(const UPNumber& rhs);

    // ๊ฐ€์งœ ํŒŒ๊ดด์ž(pseudo-destructor) ์ƒ์ˆ˜ ๋ฉค๋ฒ„ ๋ฉ”์†Œ๋“œ, 
    // ์ƒ์ˆ˜ ๊ฐ์ฒด๋ฅผ ์ œ๊ฑฐ ํ• ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—
    void destroy() const { delete this; }
    ...
private:
    ~UPNumber();    // ํŒŒ๊ดด์ž๊ฐ€ ์‚ฌ์—ญ(private)์œผ๋กœ ์„ ์–ธ๋˜์—ˆ๋‹ค.
};
ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด๋ ‡๊ฒŒ ์„ ์–ธ๋œ ํด๋ž˜์Šค๋ฅผ ๊ธฐ๋ฐ˜ํ•œ ๊ฐ์ฒด์˜ ์‚ฌ์šฉ์„ ์•Œ์•„ ๋ณด์ž๋ฉด

~cpp 
UPNumber n;                          // ์—๋Ÿฌ! ํŒŒ๊ดด์ž ์‚ฌ์—ญ(private)์ด๋ผ ์ž‘๋™ ํ• ์ˆ˜ ์—†๋‹ค.
UPNumber *p = new UPNumber;          // ํ†ต๊ณผ
...
delete p;                            // ์—๋Ÿฌ! ์—ญ์‹œ ํŒŒ๊ดด์ž ์‚ฌ์—ญ(private) ์ด์œ 
p->destroy();                        // ํ†ต๊ณผ
์ž ๋‹ค์Œ๊ณผ ๊ฐ™์ด, UPNumber ํด๋ž˜์Šค๋Š” Heap์ƒ์—์„œ๋งŒ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด๋งŒ์„ ์ƒ์„ฑ ํ• ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์˜ ๋Œ€์•ˆ์œผ๋กœ๋Š” Item 26 ๋งˆ์ง€๋ง‰์— ๋‚˜์˜จ ์˜ˆ์ œ์™€ ๊ฐ™์ด ๋ชจ๋“  ์ƒ์„ฑ์ž ๋งŒ์„ ์‚ฌ์—ญ(private)ํ™” ์‹œํ‚ค๋Š” ๊ฒƒ์ด์ง€๋งŒ, ์ด ์•„์ด๋””์–ด์˜ ๋ฌธ์ œ๋Š” ๋งŽ์€ ์ƒ์„ฑ์ž๊ฐ€ ๋ชจ๋‘ ์‚ฌ์—ญ(private)์œผ๋กœ ์žˆ์–ด์•ผ ํ•˜๊ณ , ๊ทธ๊ฒƒ๋“ค์„ ๋ฐ˜๋“œ์‹œ ๊ธฐ์–ตํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋Š” ๋ฌผ๋ก , ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋ฅผ ์ „๋ถ€ ์„ ์–ธํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋‘ ๊ณต์—ญ(public)์œผ๋กœ ์ทจ๊ธ‰ํ•˜๊ณ  ์ง€์—ญ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์ˆ˜ ์žˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ, ํŒŒ๊ดด์ž๋งŒ์„ ์‚ฌ์—ญ(private)ํ™” ์‹œํ‚ค๋Š” ๊ฒƒ์ด ๊ฐ„๋‹จํ•˜๋‹ค.

ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž์™€, ํŒŒ๊ดด์ž ์–‘์ชฝ์„ ์‚ฌ์—ญํ™”(private)์‹œ์ผœ์„œ ์ง€์—ญ ๊ฐ์ฒด(non-heap object)๋กœ ๋งŒ๋“œ๋Š”๊ฑธ ๋ง‰๋Š”๋ฐ๋„, ์•ฝ๊ฐ„์˜ ์ œํ•œ ์‚ฌํ•ญ์ด ๋ฐœ์ƒํ•œ๋‹ค. ๊ทธ ์ œํ•œ์‚ฌํ•ญ์ด๋ž€, ์ƒ์† ๊ด€๊ณ„์™€ ํฌํ•จ(containment:has-a)๊ด€๊ณ„์—์„œ ๋ฐœ์ƒํ•œ๋‹ค. ๋‹ค์Œ์˜ ์˜ˆ์ œ๋ฅผ ๋ณด๋ฉด.

~cpp 
class UPNumber { ... };             // ์ƒ์„ฑ์ž์™€ ํŒŒ๊ดด์ž ๋ชจ๋‘ ์‚ฌ์—ญ(private)๋กœ 
                                    //์„ ์–ธ๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.

class NonNegativeUPNumber: 
    public UPNumber { ... };        // ์—๋Ÿฌ! ์ƒ์„ฑ์ž์™€ ํŒŒ๊ดด์ž๋ฅผ ์ปดํŒŒ์ผ ๋ชปํ•œ๋‹ค.

class Asset {
private:
    UPNumber value;                 // ์—๋Ÿฌ! ์ƒ์„ฑ์ž์™€ ํŒŒ๊ดด์ž๋ฅผ ์ปดํŒŒ์ผ ๋ชปํ•œ๋‹ค.
    ...      
};
์ด๋Ÿฐ ๋ฌธ์ œ๋Š” ํ•ด๊ฒฐํ•˜๊ธฐ ์–ด๋ ต์ง€ ์•ˆํ•˜. ์ƒ์† ๊ด€๊ณ„์˜ ๋ฌธ์ œ๋Š” ์ƒ์„ฑ์ž๋Š” ๊ณต์—ญ(public)์œผ๋กœ ์œ ์ง€ํ•˜๊ณ , ํŒŒ๊ดด์ž๋งŒ์„ ๋ณดํ˜ธ(proteced) ๊ด€๊ณ„๋กœ ๋ฐ”๊พธ๋ฉด ๋˜๋Š”๊ฒƒ์ด๊ณ , ํฌํ•จ(contain) ๊ด€๊ณ„์—์„œ๋Š” ํ•ด๋‹น ํฌํ•จ ์ธ์ž๋ฅผ pointer๋กœ ๋ฐ”๊พธ๊ณ , ์ดˆ๊ธฐํ™” ๋ฆฌ์ŠคํŠธ์—์„œ ์ƒ์„ฑํ•ด ๋ฒ„๋ฆฌ๊ณ , ํŒŒ๊ดด์ž์—์„œ ์•ฝ๊ฐ„๋งŒ ์‹ ๊ฒฝ์จ์ฃผ๋ฉด ๋œ๋‹ค. ์œ„์˜ ์ฝ”๋“œ์˜ ํ•ด๊ฒฐ์ฑ…์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

~cpp 
class UPNumber { ... };             // ํŒŒ๊ดด์ž๋ฅผ ๋ณดํ˜ธ(protected)๋กœ ์„ค์ •ํ•œ๋‹ค.
                                    // ๋Œ€์‹  ์ƒ์„ฑ์ž๋Š” ๊ณต์—ญ(public)์œผ๋กœ ์„ค์ •ํ•œ๋‹ค. 
                                    // ๊ธฐ๋Šฅ์ƒ ์ƒ๊ด€ ์—†์œผ๋ฏ€๋กœ

class NonNegativeUPNumber:
    public UPNumber { ... };        // ์ด์ œ๋Š” ์œ ๋„๋˜๋Š” ๋ฐ๋Š” ์ง€์žฅ ์—†๋‹ค.
                                    // ์œ ๋„๋˜๋Š” ํด๋ž˜์Šค๋“ค์€ protected์ธ์ž๋Š”
                                    // ์ ‘๊ทผํ•˜๋Š”๋ฐ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค.

class Asset {
public:
    Asset(int initValue);
    ~Asset();
    ...
private:
    UPNumber *value;                // ์œ„์—์„œ์˜ ๊ฐ์ฒด ์„ ์–ธ์„ ํฌ์ธํ„ฐ๋กœ ๋ฐ”๊พธ์—ˆ๋‹ค.
};

Asset::Asset(int initValue)
: value(new UPNumber(initValue))    // ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ดˆ๊ธฐํ™” ๋ฆฌ์ŠคํŠธ๋กœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ 
{ ... }

Asset::~Asset()
{ value->destroy(); }                 // ํŒŒ๊ดด์‹œ์— ์‹ ๊ฒฝ์จ์ค€๋‹ค.(resource leak๋ฐฉ์ง€)

1.3.2. Determining Whether an Object is On The Heap : Heap์— ๊ฐ์ฒด๋ฅผ ์˜ฌ๋ฆด์ง€ ๊ฒฐ์ •ํ•˜๊ธฐ.

์ž, ์ง€๊ธˆ๊นŒ์ง€ ๋‹ค์†Œ ๋งน๋ชฉ์ (?)์œผ๋กœ Heap์˜์—ญ์— ๊ฐ์ฒด ์˜ฌ๋ฆฌ๊ธฐ์—๋งŒ ์—ด์ค‘ํ–ˆ๋‹ค. ๊ทธ๋Ÿผ ์—ฌ๊ธฐ์—์„œ๋Š” "on the heap"์˜ ์˜๋ฏธ๋ฅผ ํ™•์‹คํ•œ ํ…Œ์ŠคํŠธ๋กœ์„œ ์•Œ์•„ ๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค. ์•ž์„œ ์จ๋จน์€ NonNegativeUPNumber๋ฅผ non-heap ๊ฐ์ฒด๋กœ ๋งŒ๋“œ๋Š”๊ฑด ๋ญ ํ‹€๋ฆฌ์ง€ ์•Š์€ ๊ฒƒ์ด๋‹ค.

~cpp 
NonNegativeUPNumber n;                // fine
์ด๊ฒƒ์ด ํ—ˆ์šฉ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ž, ๊ทธ๋Ÿผ ์ง€์—ญ ๊ฐ์ฒด์ธ NonNegativeUPNumber์˜ n์—์„œ UPNumber์˜ ๋ถ€๋ถ„์€ heap์œ„์— ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ๋งž๋Š”๊ฐ€? ์ด ๋‹ต๋ณ€์€ ํด๋ž˜์Šค์˜ ์„ค๊ณ„(design)๊ณผ ์ ์šฉ(implementation)์— ๊ธฐ์ธํ•ด์•ผ ์ดํ•ด ํ• ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๋‹ต์„ ์ฐพ์•„๊ฐ€ ๋ณด์ž.UPNumber๊ฐ€ ๋ฐ˜๋“œ์‹œ heap์˜์—ญ์— ์กด์žฌ ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์— ๊ด€ํ•ด not okay๋ฅผ ๋˜์ง€๋ฉด์„œ ์‹œ์ž‘ํ•ด ๋ณด์ž. ์–ด๋–ป๊ฒŒ ์šฐ๋ฆฌ๋Š” ์ด๋Ÿฌํ•œ ์ œํ•œ ์‚ฌํ•ญ์„ ํ•ด๊ฒฐํ•ด์•ผ ํ•˜๋Š” ๊ฑธ๊นŒ?

์ด๊ฒƒ์€ ๊ทธ๋ฆฌ ์‰ฝ์ง€ ์•Š๋‹ค. UPNumber ์ƒ์„ฑ์ž๊ฐ€ ์ด๊ฒƒ์„ ์œ ๋„ ๋ฐ›์€ ๋ชจ๋“  ๊ฐ์ฒด์—๊ฒŒ, Heap์˜์—ญ ๊ธฐ๋ฐ˜์˜ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด ๋ฒ„๋ฆฌ๋ผ๊ณ  ๊ฒฐ์ • ํ•˜๋Š”๊ฒƒ์€ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š๋‹ค. ๊ธฐ๋ณธ ํด๋ž˜์Šค๋กœ ์“ฐ์ธ UPNumber์˜ ์ƒ์„ฑ์ž๊ฐ€ ๋‹ค์Œ์˜ ๋‘ ์ƒํ™ฉ์„ ์ฒดํฌํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

~cpp 
NonNegativeUPNumber *n1 =  new NonNegativeUPNumber;     // Heap์˜์—ญ
NonNegativeUPNumber n2;                                 // ๋น„ Heap์˜์—ญ
๊ทธ๋ ‡์ž๋ฏผ ์•„๋งˆ ์กฐ๊ธˆ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์˜ ์ ‘๊ทผ์„ ํ• ์ˆ˜ ์žˆ๋‹ค. ๋ฐ”๋กœ Heap์˜์—ญ์— ์˜ฌ๋ผ๊ฐ€๋Š” ๊ฐ์ฒด๋Š” ํ•ญ์ƒ new๋ฅผ ํ˜ธ์ถœํ•˜๋Š”๊ฒƒ, ๊ทธ๋ฆฌ๊ณ  ์ด new์˜ ํ˜ธ์ถœ์€ new operator์™€ operator new์™€์˜ ์ƒํ˜ธ ์ž‘์šฉ์—์„œ ์ž‘์—…์ด ์ด๋ฃจ์–ด ์ง€๋Š” ๊ฒƒ์ด๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Item 8์„ ์ฐธ๊ณ ํ•˜๊ณ , ๋‹ค์Œ๊ณผ ๊ฐ™์ด UPNumber๋ฅผ ๊ณ ์ณ์„œ ์œ ๋„๋˜๋Š” ๊ฐ์ฒด๋“ค ๋งˆ์ ธ ์ œํ•œ์„ ๊ฑธ์ˆ˜ ์žˆ๋‹ค.

~cpp 
class UPNumber {
public:
    // ๋งŒ์•ฝ non-heap ๊ฐ์ฒด๋ผ๋ฉด ๋‹ค์Œ์˜ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ ์‹œํ‚จ๋‹ค.
    class HeapConstraintViolation {};

    static void * operator new(size_t size);

    UPNumber();
    ...
private:
    static bool onTheHeap;    // ์ƒ์„ฑ์ž ๋‚ด๋ถ€์—์„œ heap์˜์—ญ์— ์ƒ์„ฑ๋˜๋Š”๊ฐ€ ํŒ๋ณ„์ธ์ž๋กœ ์“ด๋‹ค.
    ...
};

// static ์ธ์ž์˜ ์˜ ์ดˆ๊ธฐํ™” ๋ถ€๋ถ„
bool UPNumber::onTheHeap = false;

void *UPNumber::operator new(size_t size)
{
    onTheHeap = true;               // new operator๊ฐ€ ๋ถˆ๋ฆฌ๋ฉด Heap์˜์—ญ์„ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ.
    return ::operator new(size);    // operator new๋กœ์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•œ๋‹ค.
}
UPNumber::UPNumber()
{
    if (!onTheHeap) {
        throw HeapConstraintViolation();    // ํž™์ด ์•„๋‹ˆ๋ผ๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค.
    }
    ์ผ๋ฐ˜์ ์ธ ์ƒ์„ฑ ๊ณผ์ •์„ ๊ธฐ์ˆ ํ•œ๋‹ค.; 
    onTheHeap = false;                    // ๊ฐ์ฒด ์ƒ์„ฑ ํ”Œ๋ž˜์Šค๋ฅผ ์„ธํŒ…ํ•œ๋‹ค.
}
operator new๋Š” raw๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์„ ํ•˜๊ณ , ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ƒ์„ฑ์ž๋ฅผ ๋ถ€๋ฅด๋ฏ€๋กœ์„œ ์ดˆ๊ธฐํ™”๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. operator new์—์„œ onTheHeap์„ ์ฐธ์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ์ฃผ๋ฉด, ์ƒ์„ฑ์ž์—์„œ ์ด๋ฅผ ๊ฒ€์‚ฌํ•ด์„œ ์˜ˆ์™ธ ๋ฐœ์ƒ์„ ํ•˜์ง€ ์•Š๊ณ , ์ผ๋ฐ˜ ์ง€์—ญ ๋ณ€์ˆ˜๋กœ ๊ฐ์ฒด๊ฐ€ ์„ ์–ธ๋˜๋ฉด operator new๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ๊ธฐ๋ณธ ๊ฐ’์ธ false์ธํ•ด ์ƒ์„ฑ์ž์—์„œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

ํ•˜์ง€๋งŒ ์ด ์ฝ”๋“œ๋‹ค ๋Šฅ์‚ฌ๊ฐ€ ์•„๋‹Œ๊ฒƒ์ด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์„ ์„ ์–ธํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋œ๋‹ค.

~cpp 
UPNumber *numberArray = new UPNumber[100];
์ฒซ์งธ๋กœ, ์ด ๊ฒฝ์šฐ operator new๊ฐ€ ๋ถˆ๋ฆฌ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ. ๋ฉ”๋ชจ๋ฆฌ๋Š” operator new[]๋กœ ํ• ๋‹น ๋˜๊ธฐ๋•Œ๋ฌธ์—, ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด๊ณ , ๋‘˜์งธ๋กœ operator new[]์— ํ”Œ๋ž˜๊ทธ ๊ฐ’์„ ์ฃผ์—ˆ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„, ์ฒ˜์Œ ํ•œ๋ฒˆ์˜ operaotr new[]์ดํ›„์— ๊ณ„์† ์ƒ์„ฑ์ž 100๋ฒˆ์ด ๋ถˆ๋ฆฌ๋ฉด์„œ ์ฒซ๋ฒˆ์งธ ์ƒ์„ฑ์ž์—์„œ ๋‹ค์‹œ onTheHeap๋ฅผ false๋กœ ์ดˆ๊ธฐํ™” ์‹œํ‚ค๊ธฐ์—, ์ดํ›„์— ๋ถˆ๋ฆฌ๋Š” ์ƒ์„ฑ์ž๋Š” ์ „๋ถ€ onTheHeap์ด false๊ฐ’์œผ๋กœ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ ์‹œ์ผœ ๋ฒ„๋ฆฐ๋‹ค.

๋˜ ๋ฐฐ์—ด์ด ์•„๋‹ˆ๋”๋ผ๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ๋„ ์ƒ๊ฐํ•ด ๋ณธ๋‹ค.

~cpp 
new UPNumber(*new UPNumber);
์ด ๊ฒฝ์šฐ์—๋Š” ๋‘๊ฐ€์ง€์˜ new๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ operator new๋„ ๋‘๋ฒˆ ๋ถˆ๋ฆฌ๊ณ  ์ƒ์„ฑ์ž ์—ญ์‹œ ๋‘๋ฒˆ ๋ถˆ๋ฆด ๊ฒƒ์ด๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ธฐ๋Œ€ํ•˜๋Š” ๋‹ค์Œ ์ˆœ์„œ์—์„œ๋Š” ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค. (Item 8 ์ฐธ๊ณ )
  1. operator new๊ฐ€ ์ฒซ๋ฒˆ์งธ ๊ฐ์ฒด์— ๊ด€ํ•ด์„œ ๋ถˆ๋ฆฐ๋‹ค.
  2. ์ฒซ๋ฒˆ์งธ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž๊ฐ€ ๋ถˆ๋ฆฐ๋‹ค.
  3. ๋‘๋ฒˆ์งธ ๊ฐ์ฒด์˜ operator new ๊ฐ€ ๋ถˆ๋ฆฐ๋‹ค.
  4. ๋‘๋ฒˆ์งธ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž๊ฐ€ ๋ถˆ๋ฆฐ๋‹ค.
๊ทธ๋ ‡์ง€๋งŒ C++์–ธ์–ด ์ƒ์—์„œ ์ด๋Ÿฐ ๋ณด์žฅ์— ๋Œ€ํ•œ ์ŠคํŽ™์ด ์ •์˜ ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค ๊ทธ๋ž˜์„œ ์–ด๋–ค ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถ€๋ฅผ์ˆ˜๋„ ์žˆ๋‹ค.
  1. ์ฒซ๋ฒˆ์งธ ๊ฐ์ฒด์˜ operator new๊ฐ€ ๋ถˆ๋ฆฐ๋‹ค.
  2. ๋‘๋ฒˆ์งธ ๊ฐ์ฒด์˜ operator new๊ฐ€ ๋ถˆ๋ฆฐ๋‹ค.
  3. ์ฒซ๋ฒˆ์งธ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž๊ฐ€ ๋ถˆ๋ฆฐ๋‹ค.
  4. ๋‘๋ฒˆ์งธ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž๊ฐ€ ๋ถˆ๋ฆฐ๋‹ค. : ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
ํ›„์ž์˜ ์ˆœ์„œ๋กœ ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋˜์–ด๋„ ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์ž˜๋ชป์€ ์ „ํ˜€ ์—†๋‹ค. ๊ทธ๋ ‡์ง€๋งŒ set-a-bit-in-operator-new ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•œ ์ƒ๋‹จ์˜ ์˜ˆ์ œ๋Š” ๋‘๋ฒˆ์งธ ์ˆœ์„œ์—์„œ๋Š” ์‹คํŒจ ํ• ์ˆ˜ ๋ฐ–์— ์—†๋‹ค.

  • DeleteMe ์ฃผ์ œ ๋ณ€ํ™˜์ 
์ด๋Ÿฐ ์–ด๋ ค์›€์ด "๊ฐ ์ƒ์„ฑ์ž์—์„œ *this๊ฐ€ heap์˜์—ญ์— ์žˆ๋Š”๊ฐ€์— ๋Œ€ํ•œ ์—ฌ๋ถ€๋ฅผ ์•Œ์•„๋‚ธ๋‹ค." ๋ผ๋Š” ์•„์ด๋””์–ด์˜ ๊ทผ๊ฐ„์„ ํ”๋“œ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๊ฑฐ๊ธฐ์—๋‹ค๊ฐ€ ์ด๋Ÿฐ ์–ด๋ ค์›€๋“ค์€ operator new๋‚˜ operator new[] ์•ˆ์—์„œ bit set์„ ์ ๊ฒ€ํ•ด ๋ณด๋Š” ๊ฒƒ์ด ์ด๋Ÿฐ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ๊ฒฐ์ •ํ•˜๋Š”๋ฐ ์‹ ๋ขฐ์„ฑ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹˜์„ ๋ฐ˜์ฆํ•˜๊ณ  ์žˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๋ฐฉ๋ฒ•์„ ์œ„ํ•ด์„œ ํ•œ๋ฒˆ ์ƒ๊ฐํ•ด ๋ณธ๋‹ค.

์ ˆ๋งํ•˜๊ณ  ์žˆ๋Š”๊ฐ€? ๊ทธ๋Ÿผ ํ•œ๋ฒˆ ์ž„์‹œ๋กœ๋‚˜๋งˆ ์ด์‹์„ฑ์ด ๋–จ์–ด์ง€๋Š” ์˜์—ญ์—์„œ๊นŒ์ง€ ๊ทธ๋Ÿฐ ์•„์ด๋””์–ด๋ฅผ ํ™•์žฅํ•ด์„œ ์ƒ๊ฐํ•ด ๋ณด์ž. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ ๋งŽ์€ ์‹œ์Šคํ…œ ์ƒ์—์„œ ์‚ฌ์‹ค์ธ, ํ”„๋กœ๊ทธ๋žจ์˜ ์ฃผ์†Œ ๊ณต๊ฐ„์€ ์„ ํ˜•์œผ๋กœ ๋ฐฐ์—ด๋˜๊ณ , ํ”„๋กœ๊ทธ๋žจ์˜ ์Šคํ…์€ ์œ„์—์„œ ์•„๋ž˜๋กœ ๋Š˜์–ด ๋‚œ๋‹ค๊ณ  ๊ทธ๋ฆฌ๊ณ  Heap์˜์—ญ์€ ๋ฐ‘์—์„œ ์œ„๋กœ ๋Š˜์–ด๋‚œ๋‹ค๋Š” ์‚ฌ์‹ค์— ์ฃผ๋ชฉํ•ด ๋ณด์ž. ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„๋˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ชจ์Šต์ด ๋œ๋‹ค.


์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๊ตฌ์„ฑ๋œ ํ”„๋กœ๊ทธ๋žจ์˜ ์‹œ์Šคํ…œ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋น„๊ต๋ฅผ ํ• ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ?

~cpp 
// heap์— ๋Œ€ํ•œ ์—ฌ๋ถ€๊ฐ€ ์ •ํ™•ํ•˜์ง€ ์•Š์€ ์ ๊ฒ€ ๋ฐฉ๋ฒ•
bool onHeap(const void *address)
{
    char onTheStack;                // ์ง€์—ญ ์Šคํƒ ๋ณ€์ˆ˜(local stack variable)
    return address < &onTheStack;   // ์ฃผ์†Œ ๋น„๊ต   
}
ํ•จ์ˆ˜์—์„œ ์ด๋Ÿฌํ•œ ์ƒ๊ฐ์€ ์ฐธ ์˜๋ฏธ๋กญ๋‹ค. onHeapํ•จ์ˆ˜๋‚ด์—์„œ onTheStack๋Š” ์ง€์—ญ ๋ณ€์ˆ˜(local variable)์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๊ทธ๊ฒƒ์€ ์Šคํƒ์— ์œ„์น˜ํ•  ๊ฒƒ์ด๊ณ , onHeap๊ฐ€ ๋ถˆ๋ฆด๋•Œ onHeap์˜ ์Šคํ… ํ”„๋ ˆ์ž„์€ ์•„๋งˆ ํ”„๋กœ๊ทธ๋žจ ์Šคํ…์˜ ๊ฐ€์žฅ ์œ„์ชฝ์— ๋ฐฐ์น˜ ๋ ๊ฒƒ์ด๋‹ค. ์Šคํƒ์€ ๋ฐ‘์œผ๋กœ ์ฆ๊ฐ€ํ•˜๋Š” ๊ตฌ์กฐ์ด๊ธฐ์—, onTheStack๋Š” ๋ฐฉ๋“œ์‹œ ์–ด๋– ํ•œ stack-based ๋ณ€์ˆ˜๋‚˜ ๊ฐ์ฒด์— ๋น„ํ•˜์—ฌ ๋” ๋‚ฎ์€ ์œ„์น˜์˜ ๋ฉ”๋ชจ๋ฆฌ์— ์œ„์น˜ํ•˜๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๋งŒ์•ฝ address ์ธ์ž๊ฐ€ onTheStack์˜ ์œ„์น˜๋ณด๋‹ค ๋” ์ž‘๋‹ค๋ฉด ์Šคํƒ์œ„์— ์žˆ์„์ˆ˜ ์—†๋Š” ๊ฒƒ์ด๊ณ , ์ด๋Š” heap์ƒ์— ์œ„์น˜ํ•˜๋Š” ๊ฒƒ์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋Ÿฌํ•œ ๊ตฌ์กฐ๋Š” ์˜ณ๋‹ค. ํ•˜์ง€๋งŒ ์•„์ง ์ถฉ๋ถ„ํžˆ ์ƒ๊ฐํ•˜์ง€ ์•Š์€ ๊ฒƒ์ด ์žˆ๋Š”๋ฐ, ๊ทธ๊ฒƒ์€ ๊ฐ์ฒด๊ฐ€ ์œ„์น˜ํ• ์ˆ˜ ์žˆ๋Š” ์„ธ๊ฐ€์ง€์˜ ์œ„์น˜๋ฅผ ๊ฐ์•ˆํ•˜์ง€ ์•Š์€ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ œ์ด๋‹ค. ์ง€์—ญ(local) ๋ณ€์ˆ˜,๊ฐ์ฒด(variable, object)๋‚˜, Heap์˜์—ญ ์ƒ์˜ ๊ฐ์ฒด๋Š” ๊ฐ์•ˆํ•ด์ง€๋งŒ ๋นผ๋จน์€ ํ•˜๋‚˜์˜ ์˜์—ญ ๋ฐ”๋กœ ์ •์ (static)๊ฐ์ฒด์˜ ์œ„์น˜ ์˜์—ญ์ด๋‹ค.

์ด๋“ค์˜ ์œ„์น˜๋Š” ์ „๋ถ€ ์ˆ˜ํ–‰๋˜๋Š” ์‹œ์Šคํ…œ์— ์˜์กด์ ์ด๋‹ค. ํ•˜์ง€๋งŒ ๋งŽ์€ ์‹œ์Šคํ…œ์ด stack์™€ heap์ด ์„œ๋กœ๋ฅผ ํ–ฅํ•ด ์ฆ๊ฐ€ ํ•˜๋„๋ก ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ, ๊ฐ€์žฅ ์ตœํ•˜๋‹จ์— static์—ฌ์—ญ์ด ์ž๋ฆฌ ์žก๋Š” ๊ตฌ์„ฑ์œผ๋กœ ๋˜์–ด ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์•ž์— ์–ธ๊ธ‰ํ•œ ๊ทธ๋ฆผ์—์„œ ํ•œ๊ฐ€์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์ง„์งœ ๋ฉ”๋ชจ๋ฆฌ์˜ ๊ตฌ์„ฑ์ด ๋œ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ง์ด๋‹ค.:


๊ฐ‘์ž๊ธฐ ์ด์ œ ์•ž์„œ ์ž‘์„ฑํ•œ onHeapํ•จ์ˆ˜๊ฐ€ ์–ด๋– ํ•œ ์‹œ์Šคํ…œ์—์„œ๋„ ์ •ํ™•ํ•œ ์ˆ˜ํ–‰์„ ๋ชปํ•  ๊ฒƒ์ด ๋ช…๋ฐฑํ•ด ์ง„๋‹ค.:heap ๊ฐ์ฒด์™€ ์ ์ (static) ๊ฐ์ฒด๋ฅผ ๊ตฌ๋ณ„ํ•˜์ง€๋ฅผ ๋ชปํ•œ๋‹ค. ์˜ˆ์ œ์—์„œ ๋ณด๋ฉด

~cpp 
void allocateSomeObjects()
{
    char *pc = new char;    // heap ๊ฐ์ฒด: onHeap(pc)
                            // ์ด๊ฒƒ์€ true๋ฅผ ๋ฐ˜ํ™˜

    char c;                 // ์Šคํƒ(=:์ง€์—ญ) ๊ฐ์ฒด object: onHeap(&c)
                            // ์ด ์ฃผ์†Œ๋Š” false ๋ฅผ ๋ฐ˜ํ™˜

    static char sc;         // ์ •์ (static) ๊ฐ์ฒด: onHeap(&sc)
                            // ์ด ์ฃผ์†Œ๋Š” true ๋ฅผ ๋ฐ˜ํ™˜
  ...
}
์ด์ œ heap ๊ฐ์ฒด์™€ stack ๊ฐ์ฒด๋ฅผ ํŒ๋ณ„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ํ˜ผ๋ž€์ด ์˜ฌ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•์€ ์ด์‹์„ฑ์—๋„ ์—ญ์‹œ๋‚˜ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฒฐ๊ตญ compare-the-addresses ๋ฐฉ๋ฒ•์€ ์‹ ๋ขฐํ• ์ˆ˜ ์—†๋Š” ๋ฐฉ๋ฒ•์ด ๋œ๋‹ค.

์—ฌ๋‹ด์ด๋ผ๋ฉด, ์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•์€ ๋Œ€๋‹ค์ˆ˜์˜ ์‹œ์Šคํ…œ์—์„œ ์‚ฌ์‹ค์ด์ง€๋งŒ, ๊ผญ ๊ทธ๋ ‡๋‹ค๊ณ ๋Š” ๋ณผ์ˆ˜ ์—†๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ์™„์ „ํžˆ not portableํ•œ๊ฒŒ ์•„๋‹Œ semi-portable์ด๋ผ๊ณ  ํ‘œํ˜„์„ ํ•ด์•ผ ํ•˜๋‚˜. ๊ทธ๋ž˜์„œ ์•ž๋จธ๋ฆฌ์— ์ž ์‹œ๋‚˜๋งˆ ์ƒ๊ฐํ•ด ๋ณด์ž๊ณ  ํ•œ๊ฒƒ์ด๊ณ , ์ด๋Ÿฌํ•œ ์‹œ์Šคํ…œ ์˜์กด์ ์ธ ์„ค๊ณ„๋Š” ์ฐจํ›„ ๋‹ค๋ฅธ ์‹œ์Šคํ…œ์— ์ด์‹์‹œ์— ๋ฉ”๋ชจ๋ฆฌ์˜ ํ‘œํ˜„ ๋ฐฉ๋ฒ•์ด ๋‹ค๋ฅด๋‹ค๋ฉด, ์†Œํ”„ํŠธ์›จ์–ด ์ž์ฒด๋ฅผ ๋‹ค์‹œ ์„ค๊ณ„ํ•ด์•ผ ํ•˜๋Š” ์œ„ํ—˜์„ฑ์ด ์žˆ๋‹ค. ๊ทธ๋ƒฅ ์•Œ๊ณ ๋งŒ ์žˆ์ž.

  • DeleteMe ์ฃผ์ œ ๋ณ€ํ™˜์ 
์šฐ๋ฆฌ๋Š” ์•ž์ชฝ์—์„œ "delete this"๋กœ ๊ฐ€์ƒ ํŒŒ๊ดด์ž๋กœ ๊ฐ์ฒด๊ฐ€ ์Šค์Šค๋กœ๋ฅผ ์ž์‚ด ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ heap๊ฐ์ฒด๋งŒ์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ œํ•œ ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์„ ๊ธฐ์–ตํ•  ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฐ "delete this"์‹์œผ๋กœ์˜ ์ œ๊ฑฐ๋Š” ์ถ”์ฒœํ•  ๋งŒํ•œ ๋ฐฉ๋ฒ•์ด ๊ฒฐ์ฝ” ์•„๋‹ˆ๋‹ค. ( DeleteMe ๋ชจํ˜ธ) ๊ทธ๋ ‡์ง€๋งŒ, ์ง€์šฐ๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด์˜ ์•ˆ์ „์„ฑ์„ ์•„๋Š” ๊ฒƒ์€ heap์ƒ์—์„œ ํฌ์ธํ„ฐ๊ฐ€ ์ง€์นญํ•˜๋Š”๊ฐ€๋ฅผ ๊ฐ„๋‹จํžˆ ์•Œ์•„๋„ค๊ณ ์ž ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๊ฐ™์€ ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ์ž, ๋‹ค์‹œ UPNumber ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๋Š” Asset ๊ฐ์ฒด์˜ ๊ด€ํ•ด์„œ ์ƒ๊ฐํ•ด ๋ณด์ž.

~cpp 
class Asset {
private:
    UPNumber value;
    ...

};
Asset *pa = new Asset;
๋ช…๋ฐฑํžˆ *pa๋Š” heap์ƒ์— ์œ„์น˜ํ•œ ๊ฐ์ฒด์ด๋‹ค. ๋˜ ๋ช…๋ฐฑํ•˜๊ฒŒ, pa->value์˜ ํฌ์ธํ„ฐ ์—ญ์‹œ delete๋กœ ์ง€์šธ์ˆ˜ ์—†๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ด๋…€์„์ด new๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋งŒ๋“ ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋–„๋ฌธ์ด๋‹ค.

ํฌ์ธํ„ฐ๊ฐ€ ์ง€์šฐ๊ธฐ ์•ˆ์ „ํ•œ๊ฐ€์— ํŒ๋‹จ์€, ํฌ์ธํ„ฐ๊ฐ€ heap์ƒ์— ์œ„์น˜ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š”๊ฐ€๋ฅผ ์•Œ์•„๋‚ด๋Š” ๊ฒƒ๋ณด๋‹ค ์‰ฝ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์šฐ๋ฆฌ๋Š” operator new๋กœ ์ธํ•ด์„œ ๋ฐ˜ํ™˜๋˜๋Š” ์ฃผ์†Œ์˜ ๋ชจ์Œ์œผ๋กœ, ์ „์ž์˜ ์งˆ๋ฌธ์— ๊ด€ํ•ด์„œ ์•Œ์•„ ๋‚ผ์ˆ˜ ์žˆ๊ธฐ ๋–„๋ฌธ์ด๋‹ค. ์—ฌ๊ธฐ ์˜ˆ์ œ์— ๊ทธ๋Ÿฐ ๋ฌธ์ œ์— ๊ด€ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์ด ๊ธฐ์ˆ ๋˜์–ด ์žˆ๋‹ค.

~cpp 
void *operator new(size_t size)
{
    void *p = getMemory(size);          // ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๋Š” ์–ด๋–ค ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
                                        // ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ out-of-memory ์˜ˆ์™ธ๋ฅผ ์žก์„์ˆ˜ ์žˆ๋‹ค.
    ํ• ๋‹น๋œ ์ฃผ์†Œ๋ฅผ collection์— ์ €์žฅํ•œ๋‹ค.;
    return p;
}
void operator delete(void *ptr)
{
    releaseMemory(ptr);                 // ๋ฉ”๋ชจ๋ฆฌ๋ฅผ freeํ•œ๋‹ค.

    ์ด๋ฒˆ์— ์ง€์šด ์ฃผ์†Œ๋ฅผ collection์—์„œ ์ œ๊ฑฐํ•œ๋‹ค.;
}

bool isSafeToDelete(const void *address)
{
    ๋ฌผ์–ด๋ณด๋Š” ์ฃผ์†Œ๊ฐ€ collection์ƒ์— ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.;
}
์ด๋Ÿฌํ•œ ๊ฒƒ์€ ๊ฐ„๋‹จํ•˜๋‹ค. operator new๋Š” collection์— ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๋Š” ์ฃผ์†Œ๋ฅผ ๊ธฐ๋กํ•˜๊ณ , operator delete๋Š” ๊ทธ๊ฒƒ์„ ์ง€์šด๋‹ค. ๊ทธ๋ฆฌ๊ณ  isSafeToDelete๋Š” collection์— ํ•ด๋‹น ์ฃผ์†Œ๊ฐ€ ์žˆ๋Š”์ง€ ์•Œ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ๋งŒ์•ฝ operator new์™€ operator delete๊ฐ€ ์ „์—ญ ๊ณต๊ฐ„์— ์žˆ๋‹ค๋ฉด ์ด๊ฒƒ์€ ๋ชจ๋“  ํƒ€์ž…์˜ ์ž‘์—…์‹œ์— ์ ์šฉ ๋ ๊ฒƒ์ด๋‹ค.

์‹ค์ œ๋กœ ์„ธ๊ฐ€์ง€ ์ƒ๊ฐ์ด ์ด๋Ÿฌํ•œ ๋””์ž์ธ์„ ๋งค๋‹ฌ๋ฆฌ์ง€ ๋ชปํ•˜๊ฒŒ ํ•œ๋‹ค. ์ฒซ๋ฒˆ์งธ๋Š” ์ „์—ญ ๊ณต๊ฐ„์— ์–ด๋–ค๊ฒƒ์„ ์ •์˜ํ•˜๋Š” ๊ทน๋„๋กœ ํ”ผํ•˜๋ ค๋Š” ๊ฒฝํ–ฅ์ด๋‹ค. operator enw๋‚˜ operator delete๊ฐ™์€ ๋ฏธ๋ฆฌ ์ •์˜๋œ ํ•จ์ˆ˜์— ๋Œ€ํ•˜์—ฌ ํŠน๋ณ„ํ•˜๊ฒŒ ๊ณ ์นœ๋‹ค๋Š” ๊ฒƒ์€ ๋” ๊ทธ๋Ÿด ๊ฒƒ์ด๋‹ค. ๋‘˜์งธ๋กœ ํšจ์œจ์— ๊ด€ํ•œ ๋ฌธ์ œ์ด๋‹ค. ๋ชจ๋“  ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์—์„œ overhead๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋Š” ์˜๋ฏธ์ธ๋ฐ, ์ด๊ฒƒ์„ ์œ ์ง€ํ•˜๊ฒ ๋Š”๊ฐ€? ๋งˆ์ง€๋ง‰์œผ๋กœ ๊ฑฑ์ •๋˜๋Š” ๊ฒƒ์€ ํ‰๋ฒ”ํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ๊ฒƒ์œผ๋กœ isSafeToDelete์ด ๋ชจ๋“  ์ˆ˜ํ–‰์— ๊ด€ํ•˜์—ฌ ์ ์šฉ๋˜๋Š” ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒƒ์ด ๊ทผ๋ณธ์ ์œผ๋กœ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ๋ณด์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์กฐ๊ธˆ๋” ์ด์•ฝ ํ•ด๋ณด์ž๋ฉด, ๋‹ค์ค‘ ์ƒ์†์ด๋‚˜, virtual base class๊ฐ€ ๊ฐ€์ง€๋Š” ์—ฌ๋Ÿฌ๊ฒŒ์˜ ์ฃผ์†Œ๋“ค, ์ด ์ฃผ์†Œ๋“ค ๋•Œ๋ฌธ์— isSafeTo Delete์—๊ฒŒ ์ „๋‹ฌ๋˜๋Š” ์ฃผ์†Œ์— ๋Œ€ํ•œ ํ™•์‹คํ•œ ๋ณด์žฅ์ด ์—†๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Item 24, 31์ผ ์ฐธ๊ณ ํ•˜๋ผ.

  • DeleteMe)์ฃผ์ œ ์ „ํ™˜
์ž ์œ„์˜ ์ด์œ ๋กœ ์ด๋ฒˆ ์•„์ด๋””์–ด๋„ ์“ฐ๋ ˆ๊ธฐํ†ต์œผ๋กœ ๋“ค์–ด๊ฐˆ ์ฐธ์ด๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ์•„์ด๋””์–ด๋ฅผ ์ฑ„์šฉํ•ด์„œ C++์—์„œ๋Š” abstract base class๋ฅผ ์ œ๊ณตํ• ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” abstract mixin base class๋ผ๊ณ  ํ‘œํ˜„ํ•œ๋‹ค.

๊ฐ€์ƒ ํด๋ž˜์Šค๋ผ๊ณ  ํ•ด์„ ๋ ์ˆ˜ ์žˆ๋Š” abstract base ๋Š” ์ดˆ๊ธฐํ™” ๋ ์ˆ˜๊ฐ€ ์—†๋‹ค. ๋ง๋ถ™์—ฌ ๋งํ•˜์ž๋ฉด, ์ด๊ฒƒ์€ ์ˆœ์ˆ˜ ๊ฐ€์ƒ ํ•จ์ˆ˜๋ฅผ ์ตœ์†Œํ•œ ํ•˜๋‚˜ ์ด์ƒ์€ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ๋งŒ ํ•œ๋‹ค. mixin("mix in")ํด๋ž˜์Šค๋Š” ์ž˜ ์ •์˜๋œ ๊ธฐ๋Šฅ๊ณผ ์ƒ์†๋˜๋Š” ์–ด๋–ค ํด๋ž˜์Šค์™€๋„ ์ž˜ ๋ถ€ํ•ฉ๋˜๋„๋ก ์„ค๊ณ„๋˜์–ด์ ธ ์žˆ๋‹ค. ์ด๋Ÿฐ ํด๋ž˜์Šค๋“ค์€ ๊ฑฐ์˜ ํ•ญ์ƒ abstract์ด๋‹ค. ๊ทธ๋ž˜์„œ ์—ฌ๊ธฐ์—์„œ๋Š” abstract mixin base class๋Š” ์šฉ๋„๋กœ operator new๋กœ ๊ฐ์ฒด์˜ ํ• ๋‹น ์—ฌ๋ถ€๋งŒ ์•Œ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ๋งŒ์„ ์œ ๋„๋œ ํด๋ž˜์Šค์—๊ฒŒ ์ œ๊ณตํ•œ๋‹ค.

~cpp 
class HeapTracked {                  // mixin class; keeps track of
public:                              // ptrs returned from op. new

    class MissingAddress{};            // ์˜ˆ์™ธ ํด๋ž˜์Šค;์•„๋ž˜ ์ฐธ๊ณ 

    virtual ~HeapTracked() = 0;

    static void *operator new(size_t size);
    static void operator delete(void *ptr);

    bool isOnHeap() const;

private:
    typedef const void* RawAddress;
    static list<RawAddress> addresses;
};
์ด ํด๋ž˜์Šค์—์„œ list๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ฒด๋Š” C++์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ •์˜๋˜์–ด ์žˆ๋‹ค.(Item 35์ฐธ๊ณ ) list๊ฐ€ ํ•˜๋Š” ์ผ์€ ์˜ˆ์ƒ๋˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ด operator new์—์„œ ๋ฐ˜ํ™˜๋œ ์ฃผ์†Œ์˜ ์ €์žฅ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  operator delete๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๊ณ , list๋กœ ๋ถ€ํ„ฐ ํ•ด๋‹น ์ฃผ์†Œ์˜ ์—”ํŠธ๋ฆฌ๋ฅผ ์ง€์šด๋‹ค.

HeapTrack ์ ์šฉ์€ ๊ฐ„๋‹จํ•˜๋‹ค. ์™œ๋ƒํ•˜๋ฉด, operator new์™€ operator delete๊ฐ€ ์‹ค์ œ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น๊ณผ ํ•ด์ œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  list ํด๋ž˜์Šค๋Š” ์‚ฝ์ž…, ์ง€์šฐ๊ธฐ, ๊ทธ๋ฆฌ๊ณ  ๊ฒ€์ƒ‰ ์—”์ง„์„ ํฌํ•จํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ž ์—ฌ๊ธฐ ์ด๋Ÿฐ ๋‚ด์šฉ์˜ ์ ์šฉ์— ๊ด€๋ จํ•œ ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ์‚ดํ”ผ์ž.

~cpp 
// static ํด๋ž˜์Šค ๋ฉค๋ฒ„์˜ ์ •์˜๋Š” ๊ทœ์น™์ด๋‹ค.
list<RawAddress> HeapTracked::addresses;

// HeapTracked์˜ ํŒŒ๊ดด์ž๋Š” ๊ฐ€์ƒ ํด๋ž˜์Šค์˜ ์ˆœ์ˆ˜ ๊ฐ€์ƒ ํ•จ์ˆ˜์ด๋‹ค. (E14์ฐธ๊ณ )
// ๊ทธ๋ž˜์„œ ์ด ํŒŒ๊ดด์ž๊ฐ€ ๊ตฌํ˜„๋˜์–ด์•ผ ๋งŒํ•œ๋‹ค.
HeapTracked::~HeapTracked() {}

void * HeapTracked::operator new(size_t size)
{
    void *memPtr = ::operator new(size);  // ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น

    addresses.push_front(memPtr);         // ํ•ด๋‹น ์ฃผ์†Œ๋ฅผ list์˜ ์•”์ชฝ์— ์ €์žฅ
    return memPtr;
}
void HeapTracked::operator delete(void *ptr)
{
    // "iterator"๋ฅผ ์–ป์–ด์„œ list์—์„œ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ถ€๋ถ„ Item 35์ฐธ๊ณ     
    list<RawAddress>::iterator it = find(addresses.begin(), addresses.end(), ptr);

    if (it != addresses.end()) {    // ์ง€์šธ ์ฃผ์†Œ๋ฅผ ์ฐพ์•„์„œ
        addresses.erase(it);        // ํ•ด๋‹น ์—”ํŠธ๋ฆฌ๋ฅผ ์ง€์šฐ๊ณ 
        ::operator delete(ptr);     // ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๊ณ 
    } else {                        // ํ•˜์ง€๋งŒ
        throw MissingAddress();     // ptr์— ํ• ๋‹น์ด ์•ˆ๋˜์—ˆ๋‹ค๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค.
    }
}

bool HeapTracked::isOnHeap() const
{
  // *this๋กœ ํ• ๋‹น๋ฐ›์€ ๋ฉ”๋ชจ๋ฆฌ์˜ ์‹œ์ž‘์ ์„ ์–ป๋Š” ๊ณผ์ •;์ž์„ธํ•œ๊ฑด ๋ฐ‘์— ๋ณธ๋ฌธ
  const void *rawAddress = dynamic_cast<const void*>(this);

  // ์ฃผ์†Œ list์—์„œ pointer๋ฅผ ์ฐพ๊ณ  operator new์— ์˜ํ•ด ๋ฐ˜ํ™˜๋œ๋‹ค.
  list<RawAddress>::iterator it = find(addresses.begin(), addresses.end(), rawAddress);

  return it != addresses.end();      // return whether it was
}                                    // found
์ด์ฝ”๋“œ๋Š” ์•ฝ๊ฐ„ ์ƒ์†Œํ•œ listํด๋ž˜์Šค์— ๋Œ€ํ•œ ๊ฒƒ์ด ๋ณด์ผ ๊ฒƒ์ด๋‹ค. ๋ญ, ์ด์ œ๋Š” ํ•˜๋„ ๋งŽ์ด ๋‚˜์™€์„œ ๋ณ„๋กœ ์•ˆ์ƒ์†Œ ํ• ๊ฒƒ ๊ฐ™๋‹ค. STL์ด๊ณ  Item 35์— ๋ชจ๋“ ๊ฒƒ์ด ์„ค๋ช… ๋˜์–ด ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฃผ์„์„ ๋ฐ”ํƒ•์œผ๋กœ ์˜ˆ์ œ์— ๊ด€ํ•˜์—ฌ ์ถฉ๋ถ„ํžˆ ์„ค๋ช… ๊ฐ€๋Šฅํ•˜๋ฆฌ๋ผ๊ณ  ๋ณธ๋‹ค.

๋ฉค๋ฒ„ ๋ฉ”์†Œ๋“œ isOnHeap์— ์กด์žฌํ•˜๋Š” ์ด ๊ตฌ๋ฌธ์ด ๋‹ค์†Œ ์˜๋ฌธ์ด ๋“ค๊ฒƒ์ด๋‹ค.

~cpp 
const void *rawAddress = dynamic_cast<const void*>(this);
( DeleteMe ๋ชจํ˜ธ )
์œ„์—์„œ isSafeToDelete๋ฅผ ๊ตฌํ˜„ํ• ๋•Œ ๋‹ค์ค‘ ์ƒ์†์ด๋‚˜ ๊ฐ€์ƒ ๊ธฐ์ดˆ ํ•จ์ˆ˜์œผ๋กœ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๊ฐ€ ์ „์—ญ์˜ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ๋ณต์žกํ•˜๊ฒŒ ํ• ๊ฒƒ์ด๋ผ๊ณ  ์–ธ๊ธ‰ํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋ฌธ์ œ๋Š” isOnHeap์—์„œ ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค. ํ•˜์ง€๋งŒ isOnHeap๋Š” ์˜ค์ง HeapTracked๊ฐ์ฒด์— ์ ์šฉ ์‹œํ‚จ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, dynamic_cast operatror๋ฅผ ํ™œ์šฉ์œผ๋กœ ์œ„์˜ ๋ฌธ์ œ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค. ๊ฐ„๋‹จํžˆ ํฌ์ธํ„ฐ๋ฅผ dynamic_cast ํ•˜๋Š” ๊ฒƒ์€ (ํ˜น์€ const void* or volatile void* or ์•Œ๋งž๋Š” ๊ฒƒ์œผ๋กœ ๋งž์ถ”์–ด์„œ) ๊ฐ์ฒด์˜ ๊ฐ€์žฅ ์•ž์ชฝ ํฌ์ธํ„ฐ, ์ฆ‰, ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ์˜ ๊ฐ€์žฅ ์•ž์ชฝ์— ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๊ทธ๋ ‡์ง€๋งŒ dynamic_cast๋Š” ๊ฐ€์ƒํ•จ์ˆ˜๋ฅผ ํ•˜๋‚˜ ์ด์ƒ ๊ฐ€์ง€๋Š” ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ์— ํ•œํ•ด์„œ๋งŒ ํ—ˆ์šฉ ๋œ๋‹ค. isSafeToDeleteํ•จ์ˆ˜๋Š” ๋ชจ๋“  ํฌ์ธํ„ฐ์— ๊ด€ํ•ด์„œ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— dynamic_cast๊ฐ€ ์•„๋ฌด๋Ÿฐ ์†Œ์šฉ์ด ์—†๋‹ค. isOnHeap๋Š” ์กฐ๊ธˆ๋” ์„ ํƒ์˜ ํญ์ด ์žˆ์–ด์„œ this๋ฅผ const void*๋กœ dynamic_castํ•˜๋Š” ๊ฒƒ์€ ์šฐ๋ฆฌ์—๊ฒŒ ํ˜„์žฌ ๊ฐ์ฒด์˜ ๋ฉ”๋ชจ๋ฆฌ ์‹œ์ž‘์ ์˜ใ…ฃ ํฌ์ธํ„ฐ๋ฅผ ์ฃผ๊ฒŒ ๋œ๋‹ค. ๊ทธ ํฌ์ธํ„ฐ๋Š” HeapTracked::operator new๊ฐ€ ๋ฐ˜๋“œ์‹œ ๋ฐ˜ํ™˜ํ•ด์•ผ๋งŒ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ HeapTrack::operator new์˜ ์ฒ˜์Œ ๋ถ€๋ถ„์— ์žˆ๋‹ค. ๋‹น์‹ ์˜ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ dynamix_cast๋ฅผ ์ง€์›ํ•˜๋ฉด ์ด๋Ÿฌํ•œ ๊ธฐ์ˆ ์€ ์ด์‹์„ฑ์ด ๋†’๋‹ค.

์ด๋Ÿฌํ•œ ํด๋ž˜์Šค๊ฐ€ ์ฃผ์–ด์ง€๊ณ , BASIC ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์ด์ œ heap ์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ ํ• ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์„ ํด๋ž˜์Šค์—๊ฒŒ ๋ถ€์—ฌ ํ• ์ˆ˜ ์žˆ๋‹ค. ์ถ”์ ์„ ์›ํ•˜๋Š” ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ HeapTracked๋ฅผ ์ƒ์†ํ•˜๋„๋ก ๋งŒ๋“ ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด์„œ ์šฐ๋ฆฌ๊ฐ€ Asset๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ• ๋•Œ ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ heap-base ๊ฐ์ฒด์ธ์ง€ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด

~cpp 
class Asset: public HeapTracked {
private:
    UPNumber value;
    ...
};
์ด์ œ ์šฐ๋ฆฌ๋Š” Asset* ํฌ์ธํ„ฐ์— ๊ด€ํ•ด์„œ ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ฌผ์–ด ๋ณผ์ˆ˜ ์žˆ๋‹ค.

~cpp 
void inventoryAsset(const Asset *ap)
{
    if (ap->isOnHeap()) {
        ap ๋Š” heap-based asset ์ด๋‹ค. 
    }
    else {
        ap ๋Š” non-heap-based asset ์ด๋‹ค.
    }
}
์ด mixin ๊ฐ์ฒด์˜ ๋‹จ์ ์ด๋ผ๋ฉด int๋‚˜ char๋”ฐ์œ„์˜ built-in ํ˜•์—๋Š” ์จ๋จน์ง€๋ฅผ ๋ชปํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ๋“ค์€ ์ƒ์†์„ ํ• ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

1.3.3. Prohibiting Heap-Based Objects : Heap์˜์—ญ์— ๊ฐ์ฒด ์˜ฌ๋ฆฌ๊ธฐ ๋ง‰๊ธฐ

๊ธฐ๋‚˜๊ธด ์—ฌ์ •์ด๋‹ค. ์ด์ œ ๊ธ€์˜ ๋ง‰๋ฐ”์ง€์ธ ์ฃผ์ œ๋กœ ์™”๋‹ค. ์—ฌํƒœํ•œ ๊ฒƒ๊ณผ ๋ฐ˜๋Œ€๋กœ Heap์˜์—ญ์— ๊ฐ์ฒด๋ฅผ ์˜ฌ๋ฆฌ๋Š”ใ„ณ์„ ๋ง‰์„๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ? ์ด๋ฒˆ์—๋Š” ์ด๋Ÿฐ ๋ฐ˜๋Œ€์˜ ๊ฒฝ์šฐ์— ๊ด€ํ•ด์„œ ์ƒ๊ฐํ•ด ๋ณธ๋‹ค.

๊ณง ๋ฐ”๋กœ ์˜ˆ์ œ๋ฅผ ๋ณด์ž.

~cpp 
class UPNumber {
private:
    static void *operator new(size_t size);     // ์ž ์ด๋ ‡๊ฒŒ operator new๋ฅผ
                                                // ์‚ฌ์—ญ(private)์ธ์ž๋กœ ๋งŒ๋“ค์–ด ๋ฒ„๋ฆฐ๋‹ค.
    static void operator delete(void *ptr);     // operator delete ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค.
    ...
};
ํด๋ž˜์ด์–ธํŠธ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์— ๊ด€ํ•ด ๊ฐ€์ •ํ•˜์ž.

~cpp 
UPNumber n1;                         // ๋งž๋‹ค.

static UPNumber n2;                  // ์ด์ƒ ์—†๋‹ค.

UPNumber *p = new UPNumber;          // ์‚ฌ์—ญ(private)์ธ์ž์ธ opreator new๊ฐ€ ๋ถˆ๋ ค์„œ
                                     // ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

26์žฅ ๋ถ€ํ„ฐ ๊พธ์ค€ํžˆ ์ž˜ ๋ด์™”๋‹ค๋ฉด ๋ณด๋Š” ์ˆœ๊ฐ„ ์ดํ•ด๊ฐ€๋Š” ์˜ˆ์ œ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์˜๋ฌธ๊นŒ์ง€ ์ œ๊ธฐ๋œ๋‹ค. operator new[]๋Š” ์–ด๋”” ์žˆ๋Š”๊ฐ€? ์ฆ‰, heap ์˜์—ญ์— ๋ฐฐ์—ด ์„ ์–ธ๊นŒ์ง€ ๋ง‰๊ธฐ์œ„ํ•ด์„œ๋Š” operator new[]๊นŒ์ง€ ์‚ฌ์—ญ(private)์ธ์ž๋กœ ์„ ์–ธํ•ด ์ฃผ๋ฉด ๋œ๋‹ค. (์ฃผ:๋ถ„๋ช…ํžˆ ๋‹ค๋ฅธ ์ฃผ์ œ์ธ๋ฐ ์ง€๊ฒน๋‹ค. ๋„ˆ๋ฌด ๊ฐ™์€ ๊ฒƒ๋งŒ ๋ฐ˜๋ณตํ•˜๋Š” ๋А๋‚Œ์ด ๋“ ๋‹ค.)

ํฅ๋ฏธ๋กญ๊ฒŒ operator new์˜ ์‚ฌ์—ญ(private)์ธ์ž๋กœ์˜ ์„ ์–ธ์€ UPNumber๊ฐ์ฒด๋ฅผ ์ƒ์†ํ•œ ๊ฐ์ฒด์—์„œ๋„ ๊ฐ™์€ ๋Šฅ๋ ฅ์„ ๋ฐœํœ˜ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ๋‹ค์Œ์˜ ์˜ˆ์ œ๋ฅผ ๋ณด์ž.

~cpp 
class UPNumber { ... };             // ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ

class NonNegativeUPNumber:          // ์ด ํด๋ž˜์Šค์—์„œ๋Š” operator new์—๋Œ€ํ•œ 
    public UPNumber {               // ์„ ์–ธ์ด ์—†๋‹ค.
    ...
};

NonNegativeUPNumber n1;             // ์ด์ƒ ์—†๋‹ค.

static NonNegativeUPNumber n2;      // ์—ญ์‹œ ์ด์ƒ ์—†๋‹ค.

NonNegativeUPNumber *p =            // ์‚ฌ์—ญ(private)์ธ์ž์ธ opreator new๊ฐ€ ๋ถˆ๋ ค์„œ
    new NonNegativeUPNumber;        // ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
๋งˆ์ง€๋ง‰ new๋ฅผ ์“ด ๋ถ€๋ถ„์—์„œ๋Š” NonNegativeUPNumber๋ฅผ new๋กœ ์ƒ์„ฑํ• ๋•Œ ๋ถ€๋ชจ์ธ UPNumber๋ถ€๋ถ„์„ ์ƒ์„ฑํ• ๋•Œ private๋กœ ์ œ์•ฝ์ด ๋ฐœ์ƒ๋˜์–ด์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๋ฐ˜๋ฉด์— ์œ„์˜ ์ฝ”๋“œ๊ฐ€ ๊ทธ๋Œ€๋กœ๋ผ๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ ๊ฐ™์ด has-a๊ด€๊ณ„์˜ ๊ฒฝ์šฐ์—๋Š” ๊ฐ€๋Šฅํ•˜๋‹ค.

~cpp 
class Asset {
public:
  Asset(int initValue);
  ...

private:
  UPNumber value;
};

Asset *pa = new Asset(100);     // ๋งž๋‹ค.
                                // ์ด๊ฒฝ์šฐ Asset::operator new ๋‚˜ 
                                // ::operator new๋Š” ๋ถˆ๋ฆฌ์ง€๋งŒ 
                                // UPNumber::operator new๋Š” ๋ถˆ๋ฆฌ์ง€ ์•Š์œผ๋ฏ€๋กœ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•œ๋‹ค.
๋’ท๋ถ€๋ถ„์€ ์•ž์— ํ–ˆ๋“  heap์˜์—ญ์˜ ์ฃผ์†Œ ๊ธฐ๋ฐ˜์˜ ๊ฒ€์ถœ๊ณผ ์ด์‹์„ฑ์— ๋Œ€ํ•œ ๋…ผ์˜์ด๋‹ค.

1.4. Item 28: Smart pointers

  • Item 28: ๋˜‘๋˜‘ํ•œ ํฌ์ธํ„ฐ:์Šค๋งˆํŠธ ํฌ์ธํ„ฐ

Smart pointer(์ดํ•˜ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ)๋Š” ๊ฐ์ฒด์˜ ์ˆ˜์›”ํ•œ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด์„œ ํƒœ์–ด๋‚œ ๋ฐฉ๋ฒ•์ด๋‹ค. "๋ฐฉ๋ฒ•" ์ด๋ผ๊ณ  ํ‘œํ˜„ํ•œ๊ฒƒ์„ ์ฃผ์˜ํ•˜๋ผ, ํŠน๋ณ„ํžˆ ์ •ํ•ด์ง„ ๊ฒƒ์ด์•„๋‹ˆ๋ผ. ์ œ์‹œ๋œ ๋ฐฉ๋ฒ•๋ก ์„ ๋ฐ”ํƒ•์œผ๋กœ, ๋ˆ„๊ตฌ๋‚˜ ๊ตฌํ˜„ํ• ์ˆ˜ ์žˆ๋‹ค. ์ด์ „ ๋‚ด์šฉ์ค‘ ์ž˜ ๋“ฑ์žฅํ•˜๋Š” auto_ptr STL๋„ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ์•„์ด๋””์–ด๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ด๋‹ค.

C++์˜ built-in ํฌ์ธํ„ฐ๋กœ์„œ(๋‹ค์‹œ ๋งํ•ด dumb(๊ฐ€์ƒ์ •๋„๋กœ ํ•ด์„, ์ดํ•˜ "๋”๋ฏธ"๋กœ ํ‘œํ˜„) ํฌ์ธํ„ฐ) ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ์‚ฌ์šฉํ•œ๋‹ค. ์ด๋Ÿด ๊ฒฝ์šฐ ์•ž์œผ๋กœ ๋‹ค๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ๋“ค์˜ ๋ฌธ์ œ๋“ค์ด ๋…ผ์˜ ๋œ๋‹ค.
(์ž‘์„ฑ์ž์ฃผ:dumb pointer๋ฅผ ๋ค ํฌ์ธํ„ฐ ๋ผ๊ณ  ๋ถ€๋ฅด์ง€ ์•Š๊ณ  ๋”๋ฏธ(dummy) ํฌ์ธํ„ฐ๋ผ๊ณ  ๋ถ€๋ฅด๋Š”๊ฑด ์˜๋ฏธ ํ˜ธ๋„์ง€๋งŒ, ๋Šฅ๋ ฅ์„ ์ƒ์‹คํ•œ ๊ฐ€์งœ ํฌ์ธํ„ฐ์˜ ์˜๋ฏธ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ํŠนํžˆ Evangelion์—์„œ ๋”๋ฏธ ๋ผ๋Š” ํ‘œํ˜„์ด ๊ดœ์ฐฎ์€ ์–ด๊ฐ์ด๊ธฐ์— ์ฐจ์šฉํ–ˆ๋‹ค๋Š” ํ›„๋ฌธ์ด.. )
  • Construction and destruction.(์ƒ์„ฑ๊ณผ ํŒŒ๊ดด)
    ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” ์ž๋™์œผ๋กœ 0 or null์˜ ์ดˆ๊ธฐํ™”๋กœ ๋ฏธ ์ดˆ๊ธฐํ™”๋กœ ์ธํ•œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ , ํŒŒ๊ดด์‹œ์—๋„ built-in ํƒ€์ž…์˜ ํŠน์„ฑ์œผ๋กœ ์ž๋™์œผ๋กœ ํŒŒ๊ดด ์‹œ์ผœ์ค€๋‹ค.
  • Copying and assignment. (๋ณต์‚ฌ์™€ ํ• ๋‹น)
    ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์—์„œ ๊ฐ€์žฅ ์‹ฌ๊ฐํ•œ ์ œ์•ฝ ์‚ฌํ•ญ์„ ์ผ์œผํ‚ค๋Š” ๊ฒƒ์ด ๋ณต์‚ฌ์™€ ํ• ๋‹น ๋ฌธ์ œ ์ธ๋ฐ(์ฐจํ›„ ๋…ผ์˜๋œ๋‹ค.) ์ด์— ๋Œ€ํ•œ ์ด์œ ์™€, ์˜ณ๋ฐ”๋ฅธ ๋ฐฉํ–ฅ์˜ ์ œ์‹œ๋ฅผ ํ•œ๋‹ค.
  • Dereferencing. (์—ญ์ฐธ์กฐ)
    ํด๋ผ์ด์–ธํŠธ๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€์ง„ ํด๋ž˜์Šค๋ฅผ ์–ด๋–ค ๋•Œ ์–ด๋–ป๊ฒŒ ์ฐธ์กฐ๋ฅผ ํ•ด์•ผ ํ• ๊นŒ? ์˜ˆ๋ฅผ๋“ค์–ด์„œ lazy fetching(Item 17์ฐธ๊ณ )๋ฅผ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ด ์—ฌ๋Ÿฌ ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ๋ฌธ์ œ๋ฅผ ์ƒ๊ฐํ•˜์ž.

์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” built-in ํฌ์ธํ„ฐ์™€ ๊ฐ™์ด ๊ฐ•ํ•œ ํ˜• ์•ˆ์ •์„ฑ์„ ๊ฐ€์ ธ์•ผ ํ•˜๊ธฐ ๋–„๋ฌธ์— template๋กœ ๊ตฌํ˜„๋œ๋‹ค. ๋Œ€๋‹ค์ˆ˜ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ๋ชจ์Šต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์—ฌ์ง„๋‹ค.:

~cpp 
template<class T>                   // ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์œ„ํ•œ ํ…œํ”Œ๋ฆฟ
class SmartPtr {                    // ํฌ์ธํ„ฐ ๊ฐ์ฒด
public:
    SmartPtr(T* realPtr = 0);       // ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์ฃผ์–ด์ง„ ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ๋กœ 
                                    // ์ดˆ๊ธฐํ™” ์‹œํ‚ค๋Š”๋ฐ, ํ• ๋‹น๋˜์ง€ ์•Š์œผ๋ฉด 
                                    // ๋”๋ฏธ(dumb)ํฌ์ธํ„ฐ๋ฅผ 0(null)๋กœ ์ดˆ๊ธฐํ™” ์‹œํ‚จ๋‹ค.

    SmartPtr(const SmartPtr& rhs);  // ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ๋ณต์‚ฌ ์ƒ์„ฑ์ž

    ~SmartPtr();                    // ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ํŒŒ๊ดด์ž
                                    

    // ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ๊ฐ’์„ ํ• ๋‹นํ•œ๋‹ค.
    SmartPtr& operator=(const SmartPtr& rhs);

    T* operator->() const;          // ์ฐธ์กฐ ํ’€๊ธฐ:์ž๋ฃŒ์— ์ ‘๊ทผํ•˜๋„๋ก ํฌ์ธํ„ฐ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

    T& operator*() const;           // ์ฐธ์กฐ ํ’€๊ธฐ:๋งˆ์ฐฌ๊ฐ€์ง€
 
private:
    T *pointee;                     // ํ˜„์žฌ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” ๊ฒƒ
                                    // ์ด๊ฒƒ์ด ์ง์ ‘ ์ ‘๊ทผ ๋ชปํ•˜๋Š” ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ ์ด๋‹ค.
};                                    
ํ˜„์žฌ ๋ณต์‚ฌ ์ƒ์„ฑ์ž์™€(copy constructor), ํ• ๋‹น ์—ฐ์‚ฐ์ž(assignment operator)๊ฐ€ ํŠน๋ณ„ํžˆ ์„ ์–ธ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฏ€๋กœ, ๋‘˜๋‹ค ๊ณต์—ญ(public)์ธ์ž์ด๋‹ค. ๋ฌธ์ œ๋Š” ํ•จ๋ถ€๋กœ ์ด๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋”๋ฏธ(dumb)ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ™์•„ ์ง€๋ฏ€๋กœ built-in ํ˜•์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ๋‘˜์ด ์‚ฌ๋ผ์ง€๋Š” ์˜์—ญ์„ ๋ฒ—์–ด๋‚˜๋Š” ์‹œ์ ์— ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ delete ํ•˜๋ ค๊ณ  ํ• ์ˆ˜ ์žˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ๋ณด์™„์ด ํ•„์š”ํ•˜๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์ž์„ธํžˆ ๋‹ค๋ฃจ๊ธฐ์— ์•ž์„œ์„œ, ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ์ž‘์„ฑ๋˜๋Š” ํ•˜๋‚˜์˜ ๊ฐ€์ƒ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ž‘์„ฑํ•œ๋‹ค. ์ด์œ ๋Š” ์ ์ฐจ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์— ๊ด€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์ด ํ•„์š”ํ• ๋•Œ, ์ด ๊ฐ€์ƒ ์‹œ๋‚˜๋ฆฌ์˜ค์ƒ์—์„œ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜, ํ•ด๋‹น ๋ฌธ๋ฒ•์—์„œ ๊ฐ์•ˆํ•ด์•ผ ํ•  ์š”์ธ๋“ค์„ ๋…ผํ•˜๊ธฐ ์œ„ํ•ด ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ์ „์ฒด ์„ค๊ณ„๋ฅผ ์ œ์‹œํ•œ๋‹ค.

์„ค์ •๋  ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์ƒ, ๋ถ„์‚ฐ DB์—์„œ, local ์— ์žˆ๋Š” ๊ฐ์ฒด์™€, remote์— ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์ด๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ž…์žฅ์—์„œ๋Š” ๋‘˜์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์ด ์ด์›ํ™” ๋˜์–ด ์žˆ์–ด์„œ, ํ•ด๋‹น ๊ฐ์ฒด์˜ ํ”„๋กœ์‹œ์ € ํ˜ธ์ถœ์— ์ผ๊ด€์„ฑ์ด ์—†์„ ๊ฒฝ์šฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ™˜๊ฒฝ์ด ๋ถˆํŽธํ•˜๊ณ , ๋ช…์‹œ์„ฑ์ด ๋–จ์–ด์ง€๋Š” ๋“ฑ ์—ฌ๋Ÿฌ ๋ถˆ๋ฆฌํ•œ ์ ์ด ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์•„์˜ˆ ์–‘์ชฝ์˜ ๊ฐ์ฒด์— ์‚ฌ์šฉ๋ฒ•์— ๋Œ€ํ•œ ์ผ๊ด€์„ฑ์„ ๊ฐ€์ง€๊ณ  ์‹ถ์–ด ํ•œ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋กœ, ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋‘˜๋Ÿฌ์‹ธ์„œ, ํ”„๋กœ์‹œ์ €์˜ ์ผ๊ด€๋œ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ์ œ๊ณต ๋ฐ›๊ณ ์ž ํ•œ๋‹ค. ๋‹ค์Œ์€ ๊ทธ๊ฒƒ์„ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๋“ค์ด๋‹ค.:

~cpp 
template<class T>                   // ๋ถ„์‚ฐ DB์ƒ์— ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ
class DBPtr {                       // ํ…œํ”Œ๋ฆฟ
public:                              

    DBPtr(T *realPtr = 0);          // DB์ƒ์˜ DB๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋”๋ฏธ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ”ํƒ€์‘๋กœ
                                    // ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

    DBPtr(DataBaseID id);           // DB ๊ฐ์ฒด์—์„œ DB ID๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ
                                    // ์ƒ์„ฑํ•œ๋‹ค.
    ...                             // DB๋ฅผ ์œ„ํ•œ ๋‹ค๋ฅธ ์ž‘์—…๋“ค
                                    
};                                   

class Tuple {                       // ๋ฐ์ดํ„ฐ ํŽ˜์ด์Šค์˜ tuple๋ฅผ ์œ„ํ•œ ํด๋ž˜์Šค
public:
    ...
    void displayEditDialog();       // tuple์˜ ์ˆ˜์ •์„ ํ•˜๊ธฐ ์œ„ํ•œ ์œ ์ €์˜ 
                                    // ๊ทธ๋ž˜ํ”ฝ ์ธํ„ฐํŽ˜์ด์Šค(์ˆ˜์ •์ด ํ—ˆ๋ฝ๋˜๋Š” ํ•œ์—์„œ)

    bool isValid() const;           // *this ๋ฐ˜ํ™˜์˜ ์œ ํšจ์„ฑ ์ ๊ฒ€
};                                  

// T๊ฐ์ฒด๊ฐ€ ์ˆ˜์ •๋˜์–ด ํ•ด๋‹น log๋ฅผ ๋‚จ๊ธฐ๋Š” ์—ญํ• ์„ ํ•˜๋Š” ํด๋ž˜์Šค ํ…œํ”Œ๋ฆฟ
template<class T>
class LogEntry {
public:
    LogEntry(const T& objectToBeModified);
    ~LogEntry();
};

void editTuple(DBPtr<Tuple>& pt)
{
    LogEntry<Tuple> entry(*pt);     // ์ˆ˜์ •์„ ์œ„ํ•œ ํ•ด๋‹น log ์—”ํŠธ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
                                    // ์ž์„ธํ•œ ์„ค๋ช…์€ ์•„๋ž˜

    // ์œ ํšจํ•œ ๊ฐ’์ด ์ฃผ์–ด์ง€๊ธฐ ๊นŒ์ง€ ์ˆ˜์ • dialog๋ฅผ ๋›ฐ์šฐ๊ธฐ ์œ„ํ•œ ์š”๊ตฌ๋ฅผ ๊ณ„์†ํ•œ๋‹ค.
    do {
        pt->displayEditDialog();
    } while (pt->isValid() == false);
}
editTuple์˜ ๋‚ด๋ถ€์—์„œ ์ˆ˜์ •๋˜์–ด์ง€๋Š” tuple์€ ์•„๋งˆ๋„ ์›๊ฒฉ(remote)์ง€์˜ ๊ธฐ๊ณ„์— ์กด์žฌํ•˜๋Š” ๊ฐ์ฒด์ด๋‹ค. ํ•˜์ง€๋งŒ, editTuple์„ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์ด๋Ÿฌํ•œ ์‚ฌํ•ญ์— ๋Œ€ํ•˜์—ฌ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ๋•Œ๋ฌธ์— ํŠน๋ณ„ํžˆ ์ƒ๊ด€ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

editTuple๋‚ด์— LogEntry๊ฐ์ฒด๋ฅผ ์ƒ๊ฐํ•ด ๋ณด์ž. ์ˆ˜์ •์„ ์œ„ํ•œ log๋ฅผ ๋‚จ๊ธฐ๊ธฐ์œ„ํ•ด์„œ๋Š” displayEditDialog์˜ ์‹œ์ž‘๊ณผ ๋์—์„œ ๋งค๋ฒˆ ๋ถˆ๋Ÿฌ์ฃผ๋ฉด ๋˜๋Š”๋ฐ, ๊ตฌ์ง€ ์™œ ๊ตฌ์ง€ ์ด๋ ‡๊ฒŒ ํ–ˆ์„๊นŒ? ์ด์—๊ด€ํ•œ ๋‚ด์šฉ์€ ์˜ˆ์™ธ์— ๊ด€๋ จ๋œ ์ƒํ™ฉ ๋•Œ๋ฌธ์ธ๋ฐ, Item 9๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ๋œ๋‹ค.

๋‹น์‹ ์ด ๋ณผ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” ๋”๋ฏธ(dumb)ํฌ์ธํ„ฐ๋ฅผ ๊ทธ๋ƒฅ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ํฌ๊ฒŒ ์ฐจ์ด์ ์€ ์—†์–ด ๋ณด์ธ๋‹ค. ๊ทธ๊ฒƒ์€ ์บก์Аํ™”์— ๋Œ€ํ•œ ํšจ์œจ์„ฑ์„ ๋…ผํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋Š” ๊ทธ๋ƒฅ ๋”๋ฏธ(dumb)ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ์„œ, ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ์–ด๋–ค ์ผ์„ ํ–‰ํ•˜๋Š”์ง€ ํŠน๋ณ„ํžˆ ๊ด€์‹ฌ์„ ์Ÿ์„ ํ•„์š”๊ฐ€ ์—†๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๊ด€๊ฑด์ด๋‹ค.

1.4.1. Construction, Assignment and Destruction of Smart Pointers : ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ์ƒ์„ฑ, ํ• ๋‹น, ํŒŒ๊ดด

  • ์ƒ์„ฑ์ž:Constructor ๊ด€๋ จ
์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ์ƒ์„ฑ์€ ํŠน๋ณ„ํžˆ ์‹ ๊ฒฝ ์“ธ๊ฒƒ์ด ์—†๋‹ค. ์ดˆ๊ธฐํ™” ๋˜์ง€ ์•Š์•˜๋”ฐ๋ฉด ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ๋‚ด๋ถ€์˜ ์žˆ๋Š” ๋”๋ฏธ(dumb)ํฌ์ธํ„ฐ๋Š” null๋กœ ์„ธํŒ… ๋˜๋ฏ€๋กœ, ์ฐจํ›„ ํŒŒ๊ดด์‹œ์—๋„ ๋ณ„ ๋ฌธ์ œ ๋ ๊ฒƒ์ด ์—†๋‹ค.

  • ๋ณต์‚ฌ ์ƒ์„ฑ์ž(copy Constructor), ํ• ๋‹น ์—ฐ์‚ฐ์ž (assignment operator) ๊ด€๋ จ
์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ์ ์šฉ์—์„œ ๋ฌธ์ œ์‹œ ๋˜๋Š” ๊ฒƒ์ด ๋ณต์‚ฌ ์ƒ์„ฑ์ž(copy constructor), ํ• ๋‹น ์—ฐ์‚ฐ์ž(assignment operator), ํŒŒ๊ดด์ž(destuctor)์ด๋‹ค. ์ด๋“ค์—์„œ ์ฃผ์š”ํ•œ ๋…ผ์ ์ด ๋˜๋Š”๊ฒƒ์€ ownership ์ฆ‰ ์†Œ์œ ๊ถŒ์˜ ๋ฌธ์ œ์ด๋‹ค. ์†Œ์œ ๊ถŒ์— ๊ด€ํ•œ ๋ฌธ์ œ๋Š” ์ด ์•„์ดํ…œ ์ „๋ฐ˜์—์„œ ๋‹ค๋ฃจ๋Š” ์ฃผ์ œ์ด๊ณ , ํ•ด๊ฒฐ๋ฒ•๊ณผ ๊ทธ์— ๋Œ€ํ•œ ๊ฒฐ์ ์ด ๋ฐ˜๋ณต๋˜๋Š” ์‹์œผ๋กœ ์ง„ํ–‰ ํ•œ๋‹ค.

auto_ptr ํ…œํ”Œ๋ฆฟ์— ๊ด€ํ•ด์„œ ์ƒ๊ฐํ•ด ๋ณด์ž. Item 9์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์ด auto_ptr์€ heap-based ๊ฐ์ฒด๋ฅผ auto_ptr์ด ํŒŒ๊ดด ๋  ๋•Œ๊นŒ์ง€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ๋งŒ์•ฝ auto_ptr์ด ํŒŒ๊ดด๋˜์–ด์ง€๋Š” ๊ฒฝ์šฐ(์กด์žฌ ์ง€์—ญ์„ ๋ฒ—์–ด๋‚ ๋•Œ) ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด๋Š” ํŒŒ๊ดด๋˜์–ด์ง„๋‹ค. auto_ptr์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค.

~cpp 
template<class T>
class auto_ptr {
public:
    auto_ptr(T *ptr = 0): pointee(ptr) {}
    ~auto_ptr() { delete pointee; }         // ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด๋ฅผ ํŒŒ๊ดดํ•œ๋‹ค.
    ...

private:
    T *pointee;
};
์ด๋ ‡๊ฒŒ ๊ตฌํ˜„๋˜์–ด ์žˆ๋Š” ์ƒํ™ฉ์—์„œ, ๋งŒ์•ฝ auto_ptr์„ ๋ณต์‚ฌ(copy)ํ•˜๊ฑฐ๋‚˜ ํ• ๋‹น(assign)ํ•˜๋ฉด ์–ด๋–จ๊ฒŒ ๋ ๊นŒ? ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ง์ด๋‹ค.

~cpp 
auto_ptr<TreeNode> ptn1(new TreeNode);

auto_ptr<TreeNode> ptn2 = ptn1;      // ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค. ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ๊นŒ?

auto_ptr<TreeNode> ptn3;

ptn3 = ptn2;                         // operator=๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค. ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ๊นŒ?
์ด ๋‘˜(copy, assign)์˜ ์˜๋ฏธ๊ฐ€, ๋งŒ์•ฝ ๋‚ด๋ถ€์˜ ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ๋ฅผ ๋ณต์‚ฌ ํ•˜์˜€๋‹ค๋ฉด, ํ•ด๋‹น ๋‘๊ฐœ์˜ auto_ptr์€ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด, ์ฐจํ›„์— auto_ptr์ด ํŒŒ๊ดด๋˜๋Š” ์‹œ์ ์—์„œ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ ์—ฐ์†์œผ๋กœ ๋‘๋ฒˆ ํŒŒ๊ดดํ•˜๋ ค๊ณ  ์‹œ๋„ ํ• ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์€ ์ž˜๋ชป ๋œ๊ฒƒ์ด๋‹ค.

์ด๋ ‡๊ฒŒ ์ œ๊ธฐ๋˜๋Š” ๋ฌธ์ œ์˜ ๋Œ€์•ˆ์œผ๋กœ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•˜์—ฌ ๋ณต์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋’ค์— ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋งŒ๋“ค์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๊ตฌํ˜„ ์ƒํƒœ๋Š” ์ž์นซ, ๋งŽ์€ copy, assign์˜ ๋‚จ๋ฐœ์‹œ์— new์™€ delete์˜ ๋‹ค๋Ÿ‰์˜ ํ˜ธ์ถœ๋กœ, ์†๋„ ์ €ํ•˜์™€, "๊ฐ™์€ ๊ฒƒ์„ ๊ฐ™์€ ๊ฒƒ์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค." ๋ผ๋Š” ์˜๋ฏธ๋กœ ์“ด ํ”„๋กœ๊ทธ๋ž˜๋จธ์—๊ฒŒ ์˜๋ฏธ๋ฅผ ํ˜ธ๋„ ์‹œ์ผœ๋ฒ„๋ฆด์ˆ˜ ์žˆ๋‹ค.

์ด๋Ÿฐ ๋ฌธ์ œ๋Š” auto_ptr์ด ๋งŒ์•ฝ ๋ณต์‚ฌ(copying)์™€ ํ• ๋‹น(assignment)๋ฅผ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๊ทผ๋ณธ์ ์œผ๋กœ ์ œ๊ฑฐ ๋ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ auto_ptr ํด๋ž˜์Šค๋ฅผ ๊ฐ„๋‹จํžˆ ์กฐ์ž‘ํ•ด์„œ ๋ฌธ์ œ๋ฅผ ํ”ผํ•ด๋ณธ๋‹ค. ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ๊ฒƒ๊ณผ ๊ฐ™์ด ๊ฒ‰์œผ๋กœ๋Š” ๋ณต์‚ฌ์ด์ง€๋งŒ, ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์†Œ์œ ๊ถŒ(ownership)๋ฅผ ๋„˜๊ธฐ๋Š” ์ž‘์—…์„ ํ•˜๋„๋ก ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

~cpp 
template<class T>
class auto_ptr {
public:
    ...
    auto_ptr(auto_ptr<T>& rhs);         // ๋ณต์‚ฌ ์ƒ์„ฑ์ž
    auto_ptr<T>&  operator=(auto_ptr<T>& rhs);       // ํ• ๋‹น(assignment) ์—ฐ์‚ฐ์ž
    ...
};

template<class T>
auto_ptr<T>::auto_ptr(auto_ptr<T>& rhs)
{
    pointee = rhs.pointee;              // ์†Œ์œ ๊ถŒ(ownership)์„ ์ด์–‘ํ•˜๋Š” ์ž‘์—…
    rhs.pointee = 0;                    // rhs์˜ ์†Œ์œ ๊ถŒ(ownership)์„ ๋ฐ•ํƒˆํ•œ๋‹ค.
}

template<class T>
auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<T>& rhs)
{
    if (this == &rhs)                   // ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š”๊ฑด 1=1 ๊ฐ™์€ ๊ฒฝ์šฐ๋ฐ–์— 
                                        // ์—†๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์•„๋ฌด๋Ÿฐ ์ž‘์—…์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

    delete pointee;                     // ํ•ด๋‹น ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด๋ฅผ
                                        // ์‚ญ์ œํ•œ๋‹ค.

    pointee = rhs.pointee;              // ์†Œ์œ ๊ถŒ(ownership)์„ ์ด์–‘ํ•œ๋‹ค.
    rhs.pointee = 0;                    // rhs์˜ ์†Œ์œ ๊ถŒ(ownership)์„ ๋ฐ•ํƒˆํ•œ๋‹ค.

    return *this;
}
์ด๋ ‡๊ฒŒ ๋ณต์‚ฌ ์ƒ์„ฑ์ž(copy constructor)๊ฐ€ ๋ถˆ๋ฆฌ๊ฑฐ๋‚˜ ํ• ๋‹น ์—ฐ์‚ฐ์ž(assignment operator)๋ฅผ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ ์†Œ์œ ๊ถŒ(ownership)์„ ์ด์–‘ํ•œ๋‹ค. ๋งŒ์•ฝ ์ด๋Ÿฐ ์ž‘์—…์ด ์‹คํŒจํ•˜๋ฉด, ๊ฒฐ์ฝ” ๊ฐ์ฒด๋Š” ์ง€์›Œ์งˆ์ˆ˜๊ฐ€ ์—†๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋ฐฉ์‹์€ ์น˜๋ช…์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ๋ถˆ๋Ÿฌ ์˜ฌ์ˆ˜ ์žˆ๋‹ค.

๊ฐ์ฒด์˜ ์†Œ์œ ๊ถŒ(ownership)์ด auto_ptr์˜ ๋ณต์‚ฌ ์ƒ์„ฑ์ž์— ์˜ํ•˜์—ฌ ์ด์–‘๋˜๋ฏ€๋กœ, ๋งŒ์•ฝ auto_ptr์„ ๊ฐ’์— ์˜ํ•œ ์ „๋‹ฌ(by value)๋กœ ๋„˜๊ฒจ ๋ฒ„๋ฆฌ๋ฉด ๋Œ์•„์˜ฌ์ˆ˜ ์—†๋Š” ๊ฐ•์„ ๊ฑด๋„ˆ๋Š” ๊ผด์ด ๋œ๋‹ค.

~cpp 
// ๊ฐ’์— ์˜ํ•œ ์ „๋‹ฌ(by value)๋กœ auto_ptr์„ ๋„˜๊ธด๋‹ค.
void printTreeNode(ostream& s, auto_ptr<TreeNode> p)
{ s << *p; }

int main()
{
    auto_ptr<TreeNode> ptn(new TreeNode);
    ...
    printTreeNode(cout, ptn);          // ๊ฐ’์— ์˜ํ•œ ์ „๋‹ฌ(pass auto_ptr by value)
    ...
}
printTreeNode์—๊ฒŒ auto_ptr<TreeNode> ํ˜•์ธ ptn์ด ๊ฐ’์— ์˜ํ•œ ์ „๋‹ฌ(by-value)๋กœ ์ „๋‹ฌ ๋˜๋ฏ€๋กœ, printTreeNode๊ฐ€ ์ˆ˜ํ–‰๋˜๊ธฐ์ „์— ์ž„์‹œ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ๊ฑฐ๊ธฐ์— ptn์ด ๋ณต์ œ ๋œ๋‹ค. ์ด๋•Œ ๋ถˆ๋ฆฌ๋Š” ๋ณต์‚ฌ ์ƒ์„ฑ์ž(copy constructor)๋Š” ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ๋ฅผ ๋„˜๊ธฐ๋Š” ์†Œ์œ ๊ถŒ(ownership) ์ด์–‘ ์ž‘์—…์„ ํ•˜๊ฒŒ๋˜๊ณ , printerTreeNode๊ฐ€ ๋งˆ์นœ๋’ค์— ํ•ด๋‹น ๊ฐ์ฒด๋Š” ์‚ญ์ œ๋˜๊ณ , ptn์€ 0(null)๋กœ ์ดˆ๊ธฐํ™” ๋˜์–ด ์ง„๋‹ค. auto_ptr์„ ์žƒ์–ด ๋ฒ„๋ฆฐ ๊ฒƒ์ด๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๊ฐ’์œผ๋กœ์˜ ์ „๋‹ฌ์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด๋ผ๋ฉด? ์ƒ์ˆ˜ ์ฐธ์กฐ ์ „๋‹ฌ(Pass-by-reference-to-const)๋กœ ํ•œ๋‹ค๋ฉด ๋˜์ง€ ์•Š์„๊นŒ? ๊ตฌํ˜„ ์ฝ”๋“œ๋ฅผ ๋ณด์ž

~cpp 
// ์ง๊ด€์ ์ธ ์˜ˆ์ œ์ด๋‹ค. auto_ptr<TreeNode>๋ฅผ ์ƒ์ˆ˜ ์ฐธ์กฐ ์ „๋‹ฌ(Pass-by-reference-to-const)ํ•˜์˜€๋‹ค.
void printTreeNode(ostream& s, const auto_ptr<TreeNode>& p)
{ s << *p; }
ํ•ด๋‹น ์˜ˆ์ œ์˜ ์ƒ์ˆ˜ ์ฐธ์กฐ ์ „๋‹ฌ(Pass-by-reference-to-const)์˜ ์ธ์ž p๋Š” ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๊ทธ๋ƒฅ ์ฐธ์กฐ์ผ ๋ฟ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์•„๋ฌด๋Ÿฐ ์ƒ์„ฑ์ž๊ฐ€ ๋ถˆ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์†Œ์œ ๊ถŒ(ownership)์€ ๋„˜๊ธด ์ธ์ž์— ๊ทธ๋Œ€๋กœ ๋‚จ์•„ ์žˆ์œผ๋ฉฐ ๊ฐ’์œผ๋กœ์˜ ์ „๋‹ฌ(by-value)์‹œ์— ์ผ์–ด๋‚˜๋Š” ๋ฌธ์ œ๋ฅผ ๋ง‰์„์ˆ˜ ์žˆ๋‹ค.

์†Œ์œ ๊ถŒ(ownership)์„ ์ „๋‹ฌํ•˜๋Š” ๊ฐœ๋…์„ ๋‹ค๋ฃฌ๊ฑด ์ฐธ ํฅ๋ฏธ๋กญ์ง€๋งŒ, ์‚ฌ์šฉ์ž๋Š” ๊ฒฐ์ฝ” ์žฌ๋ฏธ์žˆ์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐ๋œ๋‹ค. ์ด๋Š” ๋ณต์‚ฌ(copy)๋‚˜ ํ• ๋‹น(assign)์˜ ์›๋ž˜์˜ ์˜๋ฏธ๋ฅผ ์†์ƒ ์‹œํ‚ค๋Š” ๋ฉด์ด๋ผ์„œ, ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ๋ฟ์ด๋‹ค. ๊ฐœ๋‹ค๊ฐ€ ํ•จ์ˆ˜๋“ค์ด ๋ชจ๋‘ ์ƒ์ˆ˜ ์ฐธ์กฐ ์ „๋‹ฌ(Pass-by-reference-to-const)๋กœ ์ž‘์„ฑ๋œ๋‹ค๋Š” ๋ฒ•๋„ ์—†๋‹ค. ์ฆ‰, ์“ฐ์ง€ ๋ง๋ผ๋Š” ์†Œ๋ฆฌ๋‹ค.

auto_ptr์— ๊ด€๋ จํ•œ ๋‚ด์šฉ์€ ์ด ์ฑ…์˜ ํ›„๋ฐ˜์— ๋‹ค๋ฃจ์–ด ์žˆ๋‹ค.(์ •ํ™•ํžˆ 291-294์ชฝ) ์ด๋ฒˆ์žฅ ์—ฌ๊ธฐ์— ๊ตฌํ˜„๋œ ์ฝ”๋“œ๋“ค์ด auto_ptr์˜ 100% ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ, STL์˜ auto_ptr์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ผญ ๋ณด๊ธฐ๋ฅผ ๋ฐ”๋ž€๋‹ค. ์œ„์— ์‚ฌ์‹ค ๋ฐ‘๋ง๊ณ  ๋ง์ด๋‹ค.

  • ํŒŒ๊ดด์ž(destuctor)๊ด€๋ จ
๊ทธ๋ฆฌ๊ณ  ๋Œ€๊ฒŒ์˜ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ํŒŒ๊ดด์ž๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํžˆ ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค.

~cpp 
template<class T>
SmartPtr<T>::~SmartPtr()
{
    if (*this ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” *pointee) {
        delete pointee;
    }
}
  • ๋งบ์Œ๋ง:์ฐจํ›„์— ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” Reference Counting(Item 29)์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ์ ์šฉ ๋œ๋‹ค. ๊ทธ๋•Œ ๋‹ค์‹œ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์— ๋Œ€ํ•œ ์“ฐ์ž„์— ๋Œ€ํ•˜์—ฌ ๋А๊ปด ๋ณด๊ธฐ๋ฅผ ๋ฐ”๋ž€๋‹ค.
  • 1.4.2. Implementing the Dereferencing Operators : ์—ญ์ฐธ์กฐ(Dereferencing) ์—ฐ์‚ฐ์ž์˜ ์ ์šฉ

  • ์ž‘์„ฑ์ž์ฃผ:Dereference๋ผ๋Š” ํ‘œํ˜„์€ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉ์‹œ์— ๋‚ด๋ถ€์— ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ๋ฅผ ํ†ตํ•ด์„œ ํ•ด๋‹น ๊ฐ์ฒด์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜, ๊ทธ ๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ฅผ ํ†ตํ•ด์„œ ์ ‘๊ทผํ•˜๋Š” ๊ณผ์ •์„ ์˜๋ฏธํ•œ๋‹ค. ์ด๊ฒƒ์„ Reference์˜ ๋ฐ˜๋Œ€ ์˜๋ฏธ๋กœ Dereference๋กœ ์“ด๋‹ค. ์‚ฌ์ „์—๋Š” ๋ฌผ๋ก  ์—†๋Š” ์˜๋ฏธ์ด๋‹ค. ์•ž์œผ๋กœ ์—ฌ๊ธฐ์—์„œ๋„ ์—ญ์ฐธ์กฐ๋ผ๊ณ  ํ‘œํ˜„ํ•œ๋‹ค.

  • ์—ญ์ฐธ์กฐ(Dereference)๋ฅผ ํ•˜๋Š” ์—ฐ์‚ฐ์ž๋Š” operator*์™€ operator-> ์ด๋‹ค. ๊ฐœ๋…์ ์ธ ๊ตฌ์„ฑ์„ ๋ณด์ž.

    ~cpp 
    template<class T>
    T& SmartPtr<T>::operator*() const
    {
        "์Šค๋งˆํŠธ ํฌ์ธํ„ฐ"(๋˜‘๋˜‘ํ•œ ํฌ์ธํ„ฐ ๊ธฐ๋Šฅ?)๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.;
        return *pointee;
    }
    
    ์ฒ˜์Œ ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ์ดˆ๊ธฐํ™” ํ•˜๊ฑฐ๋‚˜ pointee๊ฐ€ ์œ ํšจํ•˜๋„๋ก ๋งŒ๋“ ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ lazy fetching์ด๋ผ๋ฉด(Item 17 ์ฐธ๊ณ ) ํ•ด๋‹น ํ•จ์ˆ˜ ๋‚ด์—์„œ pointee์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๊ณผ์ •์„ ์น˜๋ฅผ ๊ฒƒ์ด๋‹ค.

    ์ด ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํ˜•์€ ์ฐธ์กฐ(reference)์ด๋‹ค. ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋Š”๊ฐ€? ๋‚œ๋ฆฌ๋„ ์•„๋‹๊ฒƒ์ด๋‹ค. ๊ฐ์ฒด์˜ ๋ฐ˜ํ™˜์€ ๊ฐ์ฒด๊ฐ€ ๋ณต์‚ฌ๋กœ ์ „๋‹ฌ์‹œ์— ์ƒ์„ฑ, ์‚ญ์ œ์—์„œ์˜ ๋น„ํšจ์œจ์€ ๋ฌผ๋ก , Item 13์— ์ œ์‹œ๋˜๋Š” slicing์„ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค. ๋˜ Item 13์—์„œ๋„ ๊ณ„์† ๋‹ค๋ฃฌ ๊ฐ€์ƒ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ์—ญ์‹œ ๊ฐ์ฒด๋ฅผ ํ†ตํ•œ ๋ฐ˜ํ™˜์€ ๋ฌธ์ œ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. Reference๋กœ ์ „๋‹ฌํ•ด๋ผ, ์ด๊ฒƒ์˜ ํšจ์œจ์„ฑ์— ๊ด€ํ•ด์„œ๋Š” ์ด๋ฏธ ๋‹ค๋ฃจ์—ˆ๊ธฐ์— ๋” ๋งํ•˜์ง€ ์•Š๋Š”๋‹ค.

    ํ•œ๊ฐ€์ง€ ๋” ์ƒ๊ฐํ•ด ๋ณด๋ฉด ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ์ธ pointee๊ฐ€ null๊ฐ’์ธ ๊ฒฝ์šฐ์— ์ฐธ์กฐ๋Š” ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ์•ˆ์‹ฌํ•ด๋ผ. ์ด์ƒํ™ฉ์€ C++์˜ ์„ค๊ณ„ ๋‹จ๊ณ„์—์„œ ์ด๋ฏธ ์›ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด๋ผ ๊ฐ€์ • ํ–ˆ๊ณ , ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ ์‹œํ‚ค๋„๋ก ์กฐ์น˜ํ•ด ๋‘์—ˆ๋‹ค. abort(์ค‘์ง€)๋ฅผ ์›ํ•˜๋Š”๊ฐ€? ๊ทธ๋ ‡๊ฒŒ ๋œ๋‹ค.

    ์—ญ์ฐธ์กฐ(dereference)์˜ ๋‹ค๋ฅธ ์—ฐ์‚ฐ์ž์ธ operator->๋ฅผ ์ƒ๊ฐํ•ด ๋ณด์ž. operator*๊ณผ ๋น„์Šทํ•œ ์—ญํ• ์ด์ง€๋งŒ ์ด๊ฒƒ์€ ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ ๊ทธ ์ž์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์•ž์˜ ์˜ˆ์ œ์ค‘, operator->๊ฐ€ ๋“ฑ์žฅํ•œ ์›๊ฒฉ DB ์ ‘๊ทผ์— ๊ด€ํ•œ ์˜ˆ์ œ๋กœ ์ƒ๊ฐํ•ด ๋ณธ๋‹ค.

    ~cpp 
    {
      LogEntry<Tuple> entry(*pt);
    
      do {
        pt->displayEditDialog();
      } while (pt->isValid() == false);
    }
    
    ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ. ๋ถ€๋ถ„์˜ ๊ตฌ๋ฌธ์ด

    ~cpp 
    pt->displayEditDialog();
    
    ์ปดํŒŒ์ผ์‹œ ์ด๋Ÿฐ ์˜๋ฏธ๋กœ ๊ต์ฒด๋˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

    ~cpp 
    (pt.operator->())->displayEditDialog();
    
    ์ƒ๊ฐํ•ด ๋ณด๋ฉด operator->์˜ ์˜๋ฏธ๋Š” ๋‘๊ฐ€์ง€๋ฅผ ๊ฐ€์งˆ์ˆ˜ ์žˆ๋‹ค. ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ๊ฐ์ฒด ์ž์ฒด์˜ ํฌ์ธํ„ฐ๋ฅผ ์ง€์นญํ•˜๋Š” ๋‹ค์†Œ ๋ณดํ†ต์˜ ์˜๋ฏธ๋กœ์„œ ํฌ์ธํ„ฐ์™€, ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ๊ฐ€ ๊ทธ๊ฒƒ์ธ๋ฐ, ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ์‚ฌ์šฉ ์šฉ๋„์ƒ ์‚ฌ์šฉ์ž๋Š” ๋”๋ฏธ(dumb)ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ ๋ฐ›๊ธฐ๋ฅผ ์›ํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ operator->๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค.

    ~cpp 
    template<class T>
    T* SmartPtr<T>::operator->() const
    {
      "์Šค๋งˆํŠธ ํฌ์ธํ„ฐ"(๋˜‘๋˜‘ํ•œ ํฌ์ธํ„ฐ ๊ธฐ๋Šฅ?)๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.;
    
      return pointee;
    }
    
    ํ•ด๋‹นํ•จ์ˆ˜๋Š” ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ „๋‹ฌ๋˜๊ณ , ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด์˜ ๊ฐ€์ƒ ํ•จ์ˆ˜๋“ค๋„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋งํฌ ๋ ๊ฒƒ์ด๋‹ค.

    ๋งŽ์€ ์–ดํ”Œ๋ฆฌ ์ผ€์ด์…˜์—์„œ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์™€ ๊ฐ™์€ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ž˜ ์•Œ์•„ ๋‘๊ธฐ๋ฅผ ๋ฐ”๋ž€๋‹ค. ํŠนํžˆ๋‚˜ ๊ณ„์† ํ™๋ณดํ•ด์„œ ์ง€๊ฒน๊ฒ ์ง€๋งŒ Reference count์ชฝ์—์„œ ๋‚˜์˜จ๋‹ค๋‹ˆ๊นŒ. ์ฃผ๋ชฉํ•˜๊ธฐ๋ฅผ.

    1.4.3. Testing Smart Pointers for Nullness : ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ๋”๋ฏธ(dumb)์ƒ์˜ null ์—ฌ๋ถ€๋ฅผ ์•Œ๊ณ  ์‹ถ์–ด!

    ์šฐ๋ฆฌ๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ์‚ฌ์šฉ์—์„œ ํ•„์š”ํ•œ ๊ฒƒ๋“ค์ธ ์ƒ์„ฑ(create), ํŒŒ๊ดด(destroy), ๋ณต์‚ฌ(copy), ํ• ๋‹น(assign), ์—ญ์ฐธ์กฐ(dereference)์— ๊ด€ํ•ด์„œ ๋…ผ์˜ํ–ˆ๋‹ค. ๊ทธ๋ ‡์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ์•„์ง ์•ˆํ•œ๊ฒƒ์ด ์žˆ๋‹ค. ๋ฐ”๋กœ ์Šค๋งˆํŠธ ํฌ์–ธํ„ฐ์˜ null์—ฌ๋ถ€๋ฅผ ์•Œ๊ณ  ์‹ถ์€๊ฒƒ ๋ฐ”๋กœ ๊ทธ๊ฒƒ์ด๋‹ค. ์ง€๊ธˆ๊นŒ์ง€์˜ ์ง€์‹๊นŒ์ง€ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค๊ณ  ํ•˜๊ณ , ๋‹ค์Œ์˜ ์ฝ”๋“œ๋ฅผ ์‹œ์ „(?) ํ•˜๊ณ ์ž ํ• ๋•Œ

    ~cpp 
    SmartPtr<TreeNode> ptn;
    
    ...
    if (ptn == 0) ...                    // ์—๋Ÿฌ!
    if (ptn) ...                         // ์—๋Ÿฌ!
    if (!ptn) ...                        // ์—๋Ÿฌ!
    
    ์ด๊ฒƒ ์ฐธ ๋ฌด์„œ์šด ์ผ์ด์ง€ ์•Š์€๊ฐ€?

    isNull ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์‰ฝ๊ฒŒ ํ•ด๊ฒฐ ๋ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ๋”๋ฏธ(dumb) ํฌ์ธํ„ฐ์™€ ๊ฐ™์ด ์“ด๋‹ค๋Š” ๊ฐœ๋…์— ๋ฐ˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์•”์‹œ์ (implicit) ํ˜•๋ณ€ํ™˜์œผ๋กœ ํ•ด๊ฒฐํ•ด ๋ณธ๋‹ค.


    ~cpp 
    template<class T>
    class SmartPtr {
    public:
        ...
        operator void*();               // ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ null์ด๋ฉด 0๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ returns 0 if the smart
        ...                             // ์•„๋‹ˆ๋ฉด 0๊ฐ€ ์•„๋‹Œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    };                                   
    
    SmartPtr<TreeNode> ptn;
    
    ...
    
    if (ptn == 0) ...                   // ์˜ฌ๋ฐ”๋ฅด๋‹ค.
    if (ptn) ...                        // ์—ญ์‹œ๋‚˜
    if (!ptn) ...                       // ์ข‹์™”์–ด! ^^
    
    ์ด๊ฒƒ์€ iostream ํด๋ž˜์Šค๋“ค์ด ์ œ๊ณตํ•˜๋Š” ํ˜•๋ณ€ํ™˜๊ณผ ๋น„์Šทํ•˜๋‹ค. ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    ~cpp 
    ifstream inputFile("datafile.dat");
    
    if (inputFile) ...                  // inputFile์ด ์ž˜ ์—ด๋ ธ๋Š”๊ฐ€์— ๊ด€ํ•ด์„œ
                                        // ํ™•์ธํ•ด ๋ณธ๋‹ค.
    
    ๋ชจ๋“  ํ˜• ๋ณ€ํ™˜ ํ•จ์ˆ˜์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ด๊ฒƒ๋„ ์—ญ์‹œ ๊ฒฐ์ ์ด ์žˆ๋Š”๋ฐ, ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ„์˜ ๋น„๊ต์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ๋œ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ๋ณด์ž.

    ~cpp 
    SmartPtr<Apple> pa;
    SmartPtr<Orange> po;
    ...
    if (pa == po) ...                   // ์ด๊ฒŒ ์ปดํŒŒ์ผ์ด ๋œ๋‹จ ๋ง์ด๋‹ค!
    
    pa์™€ po๋Š” ๊ฐ™์€ ๊ฒƒ์ด ์•„๋‹ˆ์ง€๋งŒ, ์•”์‹œ์ (implicit) ํ˜•๋ณ€ํ™˜์— ์˜ํ•ด์„œ ์•„์ฃผ ์ž˜ ์ฐธ์œผ๋กœ ์ปดํŒŒ์ผ ๋œ๋‹ค. ์ด๊ฒƒ์€ ๋Œ€๋‹ค์ˆ˜ ์•”์‹œ์ (implicit) ํ˜•๋ณ€ํ™˜์˜ ๋ฌธ์ œ์ ์ด๋‹ค.(์•„์ง๋„ ๋‚œ๊ฐํ•˜๋ฉด Item 5๋ฅผ ๋‹ค์‹œ ๋ณด์ž)

    void*์˜ ํ˜•๋ณ€ํ™˜์˜(conversion-to-void*) ๋ชจํ˜ธ์„ฑ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด const void* ํ˜•๋ณ€ํ™˜์ด๋‚˜, ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์€ bool ํ˜•๋ณ€ํ™˜์„ ๊ถŒํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋ฐฉ๋ฒ•๋„ ํ˜•๋ณ€ํ™˜๋“ค์„ ์„ž์–ด ์“ฐ๋ฉด์„œ ๋น„๊ตํ•˜๋ฉด์„œ(mixed-type comparisons) ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ ์—ญ์‹œ ํ•ด๊ฒฐํ• ์ˆ˜ ์—†๋‹ค.

    ํ•œ ๋ฐœ์ž‘ ๋ฌผ๋Ÿฌ์„œ์„œ, ํ˜•๋ณ€ํ™˜์ด ์•„๋‹Œ operator! ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด ๋ณด์ž. operator!๋ฅผ overload์‹œ์ผœ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ null์ธ๊ฒฝ์šฐ true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž.

    ~cpp 
    template<class T>
    class SmartPtr {
    public:
        ...
        bool operator!() const;            // ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ null์ผ๋•Œ returns true if and only
        ...                                // if the smart ptr is null
    };
    
    ํด๋ผ์ด์–ธํŠธ๋“ค์€ ์ด๋ ‡๊ฒŒ ์ ์šฉํ•  ๊ฒƒ์ด๋‹ค.

    {{{~c
    Valid XHTML 1.0! Valid CSS! powered by MoniWiki
    last modified 2021-02-07 05:23:49
    Processing time 0.0409 sec