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