C++

명품 C++ 5장 8번

NUMERO_K 2018. 10. 31. 19:55

8. 문제 7번의 MyIntStack를 수정하여 다음과 같이 선언하였다. 스택에 저장할 수 있는 정수의 최대 개수는 생성자에서 주어지고 size 멤버에 유지한다. MyIntStack 클래스를 작성하라.


소스코드


#include <iostream>
using namespace std;
class MyIntStack {
    int *p; // 스택 메모리로 사용할 포인터
    int size; // 스택의 최대 크기
    int tos; // 스택의 탑을 가리키는 인덱스
public:
    MyIntStack();
    MyIntStack(int size);
    MyIntStack(MyIntStack &s); // 복사 생성자
    ~MyIntStack();
    bool push(int n); // 정수 n 푸시. 꽉 차 있으면 false, 아니면 true 리턴
    bool pop(int &n); // 팝하여 n에 저장. 스택이 비어 있으면 false, 아니면 true 리턴
};
MyIntStack::MyIntStack() {
    tos = -1;
    size = 1;
    p = new int[size];
}
MyIntStack::MyIntStack(int size) {
    tos = -1;
    this->size = size;
    p = new int[size];
}
MyIntStack::MyIntStack(MyIntStack &s) {
    this->size = s.size;
    this->tos = s.tos;
    this->p = new int[s.size];
    for (int i = 0; i < s.tos; ++i)
        this->p[i] = s.p[i];
}
MyIntStack::~MyIntStack() {
    if (p)
        delete[] p;
}
bool MyIntStack::push(int n) {
    if (tos == (size-1)) return false;
    else {
        ++tos;
        p[tos] = n;
        return true;
    }
}
bool MyIntStack::pop(int& n) {
    if (tos == (-1)) return false;
    else {
        n = p[tos];
        --tos;
        return true;
    }
    
}
int main() {
    MyIntStack a(10);
    a.push(10);
    a.push(20);
    MyIntStack b = a; // 복사 생성
    b.push(30);
    int n;
    a.pop(n); // 스택 a팝
    cout << "스택 a에서 팝한 값 " << n << endl;
    b.pop(n); // 스택 b팝
    cout << "스택 b에서 팝한 값 " << n << endl;
}


실행결과




클래스가 포인터 멤버 변수를 가지고 있는 겨우, 원본 객체의 포인터 멤버 변수가 사본 객체의 포인터 멤버 변수에 복사되면, 이 둘은 같은 메모리를 가리키게 되어 문제가 일어납니다.


소멸자에서 조건문을 쓰지 않으면 이미 반환환 메모리를 다시 반환하므로, 비정상 종료가 일어납니다.