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.1490 sec