본문 바로가기
개발/C, C++

C++ 스마트 포인터 : auto_ptr

by 피로물든딸기 2021. 10. 10.
반응형

C, C++ 전체 링크

 

auto_ptr은 동적 할당한 인스턴스를 자동으로 삭제하는 스마트 포인터지만, 사용하지 않는 것이 바람직하다.

배열에 대한 기능을 지원하지 않고, 얕은 복사에 대해 문제가 있다.

 

auto_ptr을 사용하기 위해서는 memory header가 필요하다.

이제 아래 코드를 실행해보자.

#include <stdio.h>
#include <memory> // auto_ptr header
#include <iostream>

using namespace std;

class FOOD
{
private:
	int price = 0;
public:
	FOOD() { printf("FOOD created\n"); }
	~FOOD() { printf("FOOD deleted\n"); }

	virtual void printName() { cout << "FOOD Class" << endl; }
	virtual void printPrice() { cout << this->price << endl; }
	void printLine() { cout << "=================" << endl; }
};

int main(void)
{
	cout << "start main\n" << endl;

	{
		FOOD* food = new FOOD();
		//delete food;
	}

	cout << "\n==================\n" << endl;

	{
		auto_ptr<FOOD> autoFood(new FOOD);
	}

	cout << "\nend main\n" << endl;

	return 0;
}

 

food는 new로 인스턴스를 생성하였다.

scope가 종료되어도 FOOD deleted가 실행되지 않았으므로, 객체가 소멸되지 않았다.

따라서 delete로 직접 food를 없애야 한다.

{
	FOOD* food = new FOOD();
	//delete food;
}

 

auto_ptr로 할당한 autoFood의 경우 scope가 종료되어 자동으로 autoFood가 delete 되었다.

{
	auto_ptr<FOOD> autoFood(new FOOD);
}

 

하지만 FOOD 클래스를 여러 개 생성하면 런타임 에러가 발생한다.

int main(void)
{
	cout << "start main\n" << endl;

	{
		FOOD* food = new FOOD[5];
		//delete[] food;
		//delete food <- runtime error
	}

	cout << "\n==================\n" << endl;

	{
		auto_ptr<FOOD> autoFood(new FOOD[5]);
	}

	cout << "\nend main\n" << endl;

	return 0;
}

 

new를 이용한 경우에는 delete[]로 배열을 해제할 수 있지만, auto_ptr은 첫 번째 객체만 해제한다.

따라서 auto_ptr은 배열에서 사용할 수 없다.

 

또한 auto_ptr을 복사할 때 주의해야 한다. 아래의 코드를 보자.

int main(void)
{
	cout << "start main\n" << endl;

	{
		auto_ptr<FOOD> autoFood(new FOOD);
		auto_ptr<FOOD> copyFood;

		cout << "auto address : 0x" << autoFood.get() << endl;
		cout << "copy address : 0x" << copyFood.get() << endl;

		copyFood = autoFood;
		cout << "\ncopyFood = autoFood\n" << endl;

		cout << "auto address : 0x" << autoFood.get() << endl;
		cout << "copy address : 0x" << copyFood.get() << endl;
	}

	cout << "\nend main\n" << endl;

	return 0;
}

 

get을 이용하여 포인터의 주소를 확인해보면,

copyFood autoFood를 대입한 후, autoFood가 NULL을 가리키게 된다.

대입이 발생하면 r-value인 autoFood는 자신이 가리키는 주소를 copyFood에 복사해주고, 

자기 자신은 NULL로 초기화하기 때문이다.

 

auto_ptr의 대입은 복사가 일어나지 않고, 이동이 발생하게 된다.

따라서 autoFood로 메서드를 실행시키면 런타임 에러가 발생한다.

 

이러한 문제점을 바탕으로 shared_ptr이 나오게 되었다.

반응형

댓글