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