1
2 Erőforrás problémák
3
4 // ez jó így?
5 void f()
6 {
7 char *ptr = new char[1024];
8
9 g(ptr); // kivételt dobhatnak...
10 h(ptr);
11
12 delete [] ptr; // nem biztos, hogy eljutunk idáig
13 }
14
15
16 //===========================================
17
18 void f()
19 {
20 char *ptr = new char[1024];
21 try
22 {
23 g(ptr);
24 h(ptr);
25
26 delete [] ptr;
27 }
28 catch(...) // mindent elkap: nincsen finally
29 {
30 delete [] ptr;
31 throw; // az eredeti kivétel újradobása
32 }
33 }
34
35 //===========================================
36
37
38 // Stroustrup: Resource allocation is initialization
39
40 // erőforrás beburkolása osztályba: "smart pointer"
41 template <typename T>
42 class Res
43 {
44 public:
45 Res(int i) : p( new T[i] ) {}
46 ~Res() { delete [] p; }
47 T* ptr() { return p; }
48 private:
49 T* p;
50 };
51
52 void f()
53 {
54 Res r(1024); // az erőforrás lefoglalása összekapcsolódik
55 // az r objektum (jól definiált) élettartamával
56 g(ptr);
57 h(ptr);
58
59 } // itt megszűnik az r, felszámolódik a lefoglalt terület
60
61
62 Exception-safe programozás.
63
64
65
66 #ifndef MATRIX_H
67 #define MATRIX_H
68
69
70 template <class T>
71 class matrix
72 {
73 public:
74 matrix( int i, int j );
75 matrix( const matrix &other);
76 ~matrix();
77 matrix operator=( const matrix &other);
78
79 int rows() const { return x; }
80 int cols() const { return y; }
81
82 T& at( int i, int j);
83 T at( int i, int j) const;
84 T& operator()( int i, int j);
85 T operator()( int i, int j) const;
86
87 matrix operator+=( const matrix &other);
88
89 private:
90 int x;
91 int y;
92 T *v;
93 void copy( const matrix &other);
94 };
95
96 template <class T>
97 matrix<T>::matrix( const matrix &other)
98 {
99 copy( other);
100 }
101 template <class T>
102 matrix<T>::~matrix()
103 {
104 delete [] v;
105 }
106 template <class T>
107 matrix<T> matrix<T>::operator=( const matrix &other)
108 {
109 // nem kivételbiztos megoldás:
110 if ( this != &other )
111 {
112 delete [] v;
113 copy(other);
114 }
115 return *this;
116 }
117 template <class T>
118 void matrix<T>::copy( const matrix &other)
119 {
120 // nem kivételbiztos megoldás:
121 x = other.x;
122 y = other.y;
123 v = new T[x*y];
124 for ( int i = 0; i < x*y; ++i )
125 v[i] = other.v[i];
126 }
127
128 #endif /* MATRIX_H */
129
130
131 // helyes megoldás:
132
133
134 #ifndef MATRIX_H
135 #define MATRIX_H
136
137
138 template <class T>
139 class matrix
140 {
141 public:
142 matrix( int i, int j );
143 matrix( const matrix &other);
144 ~matrix();
145 matrix operator=( const matrix &other);
146
147 int rows() const { return x; }
148 int cols() const { return y; }
149
150 T& at( int i, int j);
151 T at( int i, int j) const;
152 T& operator()( int i, int j);
153 T operator()( int i, int j) const;
154
155 matrix operator+=( const matrix &other);
156
157 private:
158 int x;
159 int y;
160 T *v;
161 void copy( const matrix &other);
162 };
163
164 template <class T>
165 matrix<T>::matrix( int i, int j)
166 {
167 x = i;
168 y = j;
169 v = new T[x*y];
170 }
171 template <class T>
172 matrix<T>::matrix( const matrix &other)
173 {
174 x = other.x;
175 y = other.y;
176 v = new T[x*y];
177 try
178 {
179 for ( int i = 0; i < x*y; ++i)
180 v[i] = other.v[i];
181 }
182 catch(...)
183 {
184 // ha sikertelen a másolás, akkor felszámoljuk v-t
185 delete [] v;
186 throw; // továbbdobjuk a kivételt
187 }
188 }
189 template <class T>
190 matrix<T>::~matrix()
191 {
192 delete [] v;
193 }
194 template <class T>
195 matrix<T> matrix<T>::operator=( const matrix &other)
196 {
197 if ( this != &other )
198 {
199 // ideiglenes változóba másolunk
200 matrix temp(other);
201
202 x = temp.x;
203 y = temp.y;
204
205 // megcseréljük a "v" által mutatott területet
206 T* oldv = v;
207 v = temp.v;
208 temp.v = oldv;
209
210 } // itt temp felszámolódik: a saját régi "v" területtel
211
212 return *this;
213 }
214
215 #endif /* MATRIX_H */
216
217
218
219 Persze lehet mégjobban is:
220
221
222 #ifndef MATRIX_H
223 #define MATRIX_H
224
225
226 template <class T>
227 class matrix
228 {
229 public:
230 // matrix( int i, int j );
231 // matrix( const matrix &other);
232 // ~matrix();
233 // valószínűleg értékadó operátor sem kell
234 matrix operator=( const matrix &other);
235
236 int rows() const { return x; }
237 int cols() const { return y; }
238
239 T& at( int i, int j);
240 T at( int i, int j) const;
241 T& operator()( int i, int j);
242 T operator()( int i, int j) const;
243
244 matrix operator+=( const matrix &other);
245
246 private:
247 std::vector<T> vec; // dinamikus tömb erőforrás beburkolása
248 void copy( const matrix &other);
249 };
250
251 template <class T>
252 matrix<T> matrix<T>::operator=( const matrix &other)
253 {
254 if ( this != &other )
255 {
256 matrix temp(other);
257 vec.swap(temp.vec); // garantáltan nem dob kivételt
258 } // itt temp felszámolódik: a saját régi "v" területtel
259 return *this;
260 }
261
262 #endif /* MATRIX_H */
263
264
265
266
267
268 Kivételbiztosság (Exception safety) a standard könyvtárban
269
270
271 void f(vector<X>& v, cosnt X& g)
272 {
273 v[2] = g; // X::operator= might throw exception
274 v.push_back(g); // vector<X> 's allocator might throw exception
275 sort( v.begin(), v.end() ); // X's less than might throw exception
276 vector<X> u = v; // X's copy constructor might throw exception
277 }
278
279 Alap garancia:
280 nincsen memóriaelszivárgás
281
282 Erős garancia:
283 Az operáció tranzakcionális: vagy sikerül,
284 vagy megmarad a kiinduló állapot
285
286 Nincsen kivétel:
287 Egyes operációk garantáltan nem dobnak kivételt:
288 pl. pop_back() és swap().
289
290
291 vector deque list map
292
293 clear() nothrow(copy) nothrow(copy) nothrow nothrow
294
295 erase() nothrow(copy) nothrow(copy) nothrow nothrow
296
297 1-elem insert() strong(copy) strong(copy) strong strong
298
299 N-elem insert() strong(copy) strong(copy) strong basic
300
301 merge() -- -- nothrow(comp) --
302
303 push_back() strong strong strong --
304
305 push_front() -- strong strong --
306
307 pop_back() nothrow nothrow nothrow --
308
309 pop_front() -- nothrow nothrow --
310
311 remove() -- -- nothrow(comp) --
312
313 remove_if() -- -- nothrow(pred) --
314
315 reverse() -- -- nothrow --
316
317 splice() -- -- nothrow --
318
319 swap() nothrow nothrow nothrow nothrow
320 (copy-of-comp)
321 unique() -- -- nothrow(comp) --
322