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