A. Utilité et comportement________________________________________________
1. Introduction
2. Notion de propriété
3. Notion de destruction
4. Notion de copie
B. Cas dutilisation_______________________________________________________
1. Encapsulation de variables
membre de type pointeur.
2. Dans les appels de fonction :
en paramètre et en valeur de retour.
3. Lauto_ptr constant.
C. Limites______________________________________________________________
1. Ne doit pas pointer sur un
objet de la pile.
2. Conversions et méthodes templates.
3. Lauto_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 dimplémentation______________________________________________
G. Bibliographie_________________________________________________________
- C++ garantie la résistance lors de la destruction dun pointeur nul
- C++ nappelle les destructeurs dobjet que sur les objets complétement construits (sinon il ne sait quoi détruire !).
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
5.
auto_ptr<P> pt1(new P("p3"));
6.
auto_ptr<P> pt2;
7.
pt2 = pt1;
8.
pt1->doIt(); // ERREUR
a lexecution sauf pour MSVC
Avant tout, dans quels cas lutilisation dun attribut de type pointeur est elle justifiée ?
Lors dune construction de lattribut externe, suivie dune 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.
}
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.
}
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. };
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. };
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) {/*...*/}
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());
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. }
26/08/2001