L'auto_ptr de la Standard Template Library

 

A.    Utilité et comportement________________________________________________
1.     Introduction
2.     Notion de propriété
3.     Notion de destruction
4.     Notion de copie

B.    Cas d’utilisation_______________________________________________________
1.     Encapsulation de variables membre de type pointeur.
2.     Dans les appels de fonction : en paramètre et en valeur de retour.
3.     L’auto_ptr constant.

C.    Limites______________________________________________________________
1.     Ne doit pas pointer sur un objet de la pile.
2.     Conversions et méthodes templates.
3.     L’auto_ptr passé par copie.
4.     Incompatibilité induite avec la STL.

D.    Notions connexes_____________________________________________________
1.     « Atomicité » dans une fonction
2.     « Pimpl », ou pare-feu logiciel.

E.     Conclusion__________________________________________________________

F.     Exemple d’implémentation______________________________________________

G.    Bibliographie_________________________________________________________


A.   Utilité et comportement

1.     Introduction

-        C++ garantie la résistance lors de la destruction d’un pointeur nul

-        C++ n’appelle les destructeurs d’objet que sur les objets complétement construits (sinon il ne sait quoi détruire !).

2.     Notion de propriété

1.             auto_ptr<P> pt(new P("p1"));
2.             pt.reset(new P("p2"));    // detruit ancien P, re-init pt
3.           P* p = pt.release();  // pour reprendre le controle
4.                                 // pt.get() == 0

3.     Notion de destruction

4.     Notion de copie

5.         auto_ptr<P> pt1(new P("p3"));
6.         auto_ptr<P> pt2;
7.         pt2 = pt1;
8.         pt1->doIt();  // ERREUR a l’execution sauf pour MSVC

B.   Cas d’utilisation

1.     Encapsulation de variables membre de type pointeur.

Avant tout, dans quels cas l’utilisation d’un attribut de type pointeur est elle justifiée ?

Lors d’une construction de l’attribut externe, suivie d’une prise de possession ?

9.         class BookEntry
10.     {
11.     public:
12.         BookEntry::BookEntry(
13.             const string& name,
14.             const string& adress,
15.             const string& imageFileName,
16.             const string& audioClipFileName);
17.      
18.         BookEntry::~BookEntry();
19.      
20.     private:
21.         //...
22.         string
23.         _name;
24.      
25.         const auto_ptr<Image>
26.         _image;
27.      
28.         const auto_ptr<AudioClip>
29.         _audioClip;
30.      
31.         auto_ptr<Image>
32.         createImage(const string imageFileName);
33.      
34.         auto_ptr<AudioClip>
35.         createAudioClip(const string audioClipFileName);
36.     }
37.      
38.     BookEntry::
39.     BookEntry(
40.         const string& name,
41.         const string& adress,
42.         const string& imageFileName,
43.         const string& audioClipFileName)
44.     :
45.         _name(name),
46.         _adresse(adresse),
47.         _image(createImage(imageFileName)),
48.         _audioClip(createAudioClip(audioClipFileName))
49.     {
50.     }
51.      
52.      
53.     BookEntry::
54.     ~BookEntry()
55.     {
56.         // Nothing to do !!!
57.     }
58.      
59.     auto_ptr<Image>
60.     createImage(const string imageFileName)
61.     {
62.         if (imageFileName.isEmpty())
63.         {
64.             return auto_ptr<Image>();
65.         }
66.         else
67.         {
68.             return auto_ptr<Image>(new Image(imageFileName));
69.         }
70.     }
71.      
72.     auto_ptr<AudioClip>
73.     createImage(const string audioClipFileName)
74.     {
75.         if (audioClipFileName.isEmpty())
76.         {
77.             return auto_ptr< AudioClip >();
78.         }
79.         else
80.         {
81.             return auto_ptr<AudioClip>(
82.                 new AudioClip(audioClipFileName));
83.         }
84.     }

2.     Dans les appels de fonction : en paramètre et en valeur de retour.

85.     auto_ptr<A> source()
86.     {
87.         return auto_ptr<A>(new A());
88.     }
89.      
90.     void puit(auto_ptr<A> aPt)
91.     {
92.         // prise en charge du A*, sinon destruction
93.     }

3.     L’auto_ptr constant.

C.   Limites

1.     Ne doit pas pointer sur un objet de la pile.

Sinon le destructeur risque d’être appelé deux fois sur un même objet…

94.     void justDoIt()
95.     {
96.         A a("id");            // a est sur la pile
97.         //...
98.         auto_ptr<A> aPt(&a);  // a eviter
99.         // ...
100. };

2.     Conversions et méthodes templates.

101. class Derivee : public Base { /* ... */ };
102. // ...
103. auto_ptr<Derivee> deriveePt(new Derivee("Derivee"));
104. auto_ptr<Base> basePt = deriveePt;

105. template <class T>
106. class auto_ptr
107. {
108.     //...
109.     template <class Y>
110.     auto_ptr<Y> & operator=(auto_ptr<Y> & ptr)
111.     { /* ... */ }
112.     // ...
113. };

3.     L’auto_ptr passé par copie.

Relatif au transfert de propriété et à la copie destructive.

114. void justDoIt(auto_ptr<T> pt1) {/*...*/}
115. // ...
116. auto_ptr<T> pt2(new T(2));
117. justDoIt(pt2); // *pt2 est detruit car transfere
118. assert(0 == pt2.get());

La solution est :

119. void justDoIt(auto_ptr<T> & pt1) {/*...*/}

120. void justDoIt(T* p) {/*...*/}

4.     Incompatibilité induite avec la STL.

121. std::vector<auto_ptr<T>> v;
122. v.push_back(auto_ptr<T>(new T(1)));
123. v.push_back(auto_ptr<T>(new T(4)));
124. v.push_back(auto_ptr<T>(new T(3)));
125. v.push_back(a);  // a perd le control de son pointeur
126. v.push_back(auto_ptr<T>(new T(2)));
127. sort(v.begin(),v.end());

D.   Notions connexes

1.     « Atomicité » dans une fonction

2.     « Pimpl », ou pare-feu logiciel.

E.   Conclusion

F.    Exemple d’implémentation

128. template<class T>

129. class auto_ptr

130. {

131. public:

132.     explicit auto_ptr(T *p = 0);  // see Item 5 for a

133.                                   // description of "explicit"

134.     template<class U>             // copy constructor member

135.     auto_ptr(auto_ptr<U>& rhs);   // template (see Item 28):

136.                                   // initialize a new auto_ptr

137.                                   // with any compatible

138.                                   // auto_ptr

139.     ~auto_ptr();

140.     template<class U>

141.  

142.     auto_ptr<T>&                  // assignment operator

143.     operator=(auto_ptr<U>& rhs);  // member template (see

144.                                   // Item 28): assign from any

145.                                   // compatible auto_ptr

146.  

147.     T&                            // see Item 28

148.     operator*() const;

149.  

150.     T*

151.     operator->() const;           // see Item 28

152.  

153.     T*                            // return value of current

154.     get() const;                  // dumb pointer

155.  

156.     T*                            // relinquish ownership of

157.     release();                    // current dumb pointer and

158.                                   // return its value

159.  

160.     void                          // delete owned pointer;

161.     reset(T *p = 0);              // assume ownership of p

162.  

163. private:

164.     T*

165.     _pointee;

166. };

167.  

168. template<class T> inline

169. auto_ptr<T>::

170. auto_ptr(T *p)

171. :

172.     _pointee(p)

173. {

174. }

175.  

176. template<class T> template<class U> inline

177. auto_ptr<T>::

178. auto_ptr(auto_ptr<U>& rhs)

179. :

180.     _pointee(rhs.release())

181.  

182. template<class T> inline

183. auto_ptr<T>::

184. ~auto_ptr()

185. (

186.     delete _pointee;

187. }

188.  

189. template<class T> template<class U> inline auto_ptr<T>& auto_ptr<T>::

190. operator=(auto_ptr<U>& rhs)

191. {

192.     if (this != &rhs)

193.     {

194.         reset(rhs.release());

195.     }

196.     return *this;

197. }

198. template<class T> inline T& auto_ptr<T>::

199. operator*() const

200. {

201.     return *_pointee;

202. }

203.  

204. template<class T> inline T* auto_ptr<T>::

205. operator->() const

206. {

207.     return _pointee;

208. }

209.  

210. template<class T> inline T*

211. auto_ptr<T>::

212. get() const

213. {

214.     return _pointee;

215. }

216.  

217. template<class T> inline T*

218. auto_ptr<T>::

219. release()

220. {

221.     T *oldPointee = _pointee;

222.     _pointee = 0;

223.     return oldPointee;

224. }

225.  

226. template<class T> inline void

227. auto_ptr<T>::

228. reset(T *p)

229. {

230.     delete _pointee;

231.     _pointee = p;

232. }

G.  Bibliographie

26/08/2001

www.2ia.net © 2001-2004