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