بخش ۱۳ - مدیریت حافظه در کلاسها
در این بخش ساختمان دادهی پشته در قالب یک کلاس پیادهسازی میشود. در این پیادهسازی برای نگهداری عناصر پشته از آرایه استفاده میشود. همانگونه که خواهیم دید برای مدیریت درست حافظه در شرایط مختلف نیاز به تعریف مخرب و سازندهی کپی و همچنین سربارگذاری عملگر جایگزینی داریم.
فهرست مثالها
کلاس پشته در حالی که پسدادن حافظهی تخصیصیافته برای نگهداری عناصر توسط مخرب انجام میشود.
#include <iostream> using namespace std; #define DEFAULT_SIZE 10 class invalid_operation_ex {}; class stack { public: stack(int size); ~stack(); void push(int x); void pop(); int top() const; int elem_count() const { return count; } private: int *elements; int size; int count; }; stack::stack(int s = DEFAULT_SIZE) { cout << "--constructor called\n"; size = s; elements = new int[size]; count = 0; } stack::~stack() { cout << "--destructor called\n"; delete[] elements; } void stack::push(int x) { if (count >= size) throw invalid_operation_ex(); elements[count] = x; count++; } void stack::pop() { if (count > 0) count--; else throw invalid_operation_ex(); } int stack::top() const { if (count > 0) return elements[count-1]; else throw invalid_operation_ex(); } int main() { stack s; s.push(4); cout << s.top() << endl; }
این مثال نشاندهندهی مشکلی است که هنگام ساختن کپی از اشیایی پیش میآید که حافظهی پویا به آنها تخصیص یافته.
void print_stack(stack s) { while (s.elem_count() > 0) { cout << s.top() << ' '; s.pop(); } cout << endl; } int main() { stack u; u.push(4); u.push(5); u.push(12); print_stack(u); u.pop(); u.pop(); u.pop(); // Explain the result of execution of this code }
برای رفع مشکل مثال قبل، باید برای این کلاس سازندهی کپی تعریف کنیم تا هنگام کپی گرفتن از روی یک شیء به طور خودکار تخصیص حافظه را به عهده بگیرد.
class stack { stack(const stack&); }; stack::stack(const stack& s) { cout << "-- copy constructor called\n"; size = s.size; count = s.count; elements = new int[size]; for (int i = 0; i < count; i++) elements[i] = s.elements[i]; } void print_stack(stack s) { while (s.elem_count() > 0) { cout << s.top() << ' '; s.pop(); } cout << endl; } int main() { stack u; u.push(4); u.push(5); u.push(12); print_stack(u); u.pop(); u.pop(); u.pop(); // Explain the result of execution of this code }
این مثال نشان میدهد برای استفادهی بیاشکال از کلاسی که تخصیص حافظهی پویا دارد لازم است به عملگر جایگزینی هم توجه شود.
int main() { stack u; u.push(4); u.push(5); u.push(12); stack v = u; stack w; w = u; // Explain the result of execution of this code }
برای رفع مشکل مثال قبل، باید عملگر جایگزینی را سربارگذاری کنیم.
class stack { stack& operator=(const stack&); }; stack& stack::operator=(const stack& s) { if (this == &s) return *this; count = s.count; size = s.size; delete[] elements; elements = new int[size]; for (int i = 0; i < count; i++) elements[i] = s.elements[i]; return *this; } int main() { stack u; u.push(4); u.push(5); u.push(12); stack w; w = u; }