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