IT 프로그래밍/객체지향프로그래밍

동적 생성 개체의 삭제와 쓰레기

기술1 2024. 6. 16. 14:39
반응형

동적 객체는 delete를 해줘야한다

동적 생성된 객체는 명시적으로 delete를 해줘야 삭제가 됩니다. 다른 객체들은 그 객체의 scope를 벗어나면 자동 삭제되지만 동적 생성은 아닙니다. 

 

그러므로 반드시 delete를 해주어야 하는데요. 동적 생성된 객체의 주소를 저장하는 포인터는 그 포인터 변수의 scope를 벗어나면 자동 삭제됩니다. 이 경우 동적 생성된 객체의 주소를 잃어버리게 됩니다.

 

이렇게 주소를 잃어버리고 삭제되지 않은 동적 객체를 쓰레기라고 부릅니다. 이 누적된 쓰레기는 프로그램의 성능을 저하시킵니다. 

 

class MyPoint {
public:
	double x, y;
	MyPoint() = default;
	MyPoint(double a, double b) : x(a), y(b) {}
};

int main() {
	MyPoint a(0, 0);
	someFunc1(a);
	MyPoint* r2 = someFunc2(a);
	someFunc3();
}

void someFunc1(MyPoint s) {
	MyPoint p(1, 2);
}

MyPoint* someFunc2(MyPoint s) {
	MyPoint* ptr = new MyPoint(3, 4);

	return ptr;
}

void someFunc3() {
	MyPoint* ptr = new MyPoint(5, 6);

	delete ptr;
}

처음 someFunc1의 s와 p는 동적 생성객체가 아니므로 이 함수가 종료되면 자동 삭제됩니다.

 

ptr이 가리키는 MyPoint 객체는 동적으로 생성되었습니다. 이 함수가 종료되면 포인터 변수 ptr은 자동으로 소멸됩니다. 하지만 이 객체의 주소를 return하므로 main함수가 이 객체의 주소를 갖게 됩니다. 문제가 없습니다. 

 

somefunc3 함수가 종료되면 포인터 변수 ptr은 자동으로 소멸됩니다. 그러면 동적 생성된 객체의 주소를 아무도 기억하지 못합니다. 따라서 delete명령으로 이 객체를 삭제하지 않으면 쓰레기가 됩니다. 

 

배열의 동적 배열

동적 배열을 생성하면 new는 배열의 주소가 아니라 배열의 첫 번째 원소의 주소를 반환합니다. 따라서 포인터의 타입이 int *, string *, Term * 입니다. 

 

배열의 타입명을 입력하고 동적으로 생성합니다. 

배열의 첫번째 칸은 반환해주는 것입니다. 지금까지는 어떤 객체를 동적 생성하면 주소 전체 를 리턴해주었지만 배열에 대한 포인터가 아니라 배열 전체가 아닌 첫 번재 원소의 주소를 하기 때문에 포인터의 타입이 배열 첫 번째 원소의 타입을 반환해줘야 하는 것입니다. (배열은 원래 예외가 많습니다)

Term* pta = new Term[10];

Term t1(2, 3), t2(4, 5), t3(6, 7);

이렇게 길이가 10인 Term타입의 배열을 동적 생성을 해주었습니다. 

pta[0] = t1;
pta[1] = t2;
pta[2] = t3;

그렇다면 이렇게 배열의 첫 번째 원소의 주소인 pta를 마치 배열의 이름인 것처럼 사용을 할 수 있습니다.

 

for (int i = 0; i < 3; i++)
	cout << pta[i].coef << ", " << pta[i].expo << endl;

이렇게도 할 수 있습니다.

 

 

int* pia = new int[10];
string* psa = new string[10];
Term* pta = new Term[10];
delete[] pia;
delete[] psa;
delete[] pta;

앞에 delete 앞에 []를 해주어야지 삭제가 됩니다. 이는 배열만의 특이한 규칙입니다. 

반응형