인프런 커뮤니티 질문&답변
8:10 질문입니다
해결된 질문
작성
·
179
0
안녕하세요!
1.
8:10초에
AutoPtr<Resource> res = new Resource; 는
포인터가 아니라 자체가 스마트 포인터이기 때문에 *res가 아닌 res로 한다고 하셨는데
new Resource는 메모리 동적할당을 받아서 주소를 가지고 있는데 res에 넣는게 가능한건가요??
2.
AutoPtr.h 헤더 내부에
AutoPtr(AutoPtr &a)
{
m_ptr = a.m_ptr;
a.m_ptr = nullptr;
}
이 함수는 디버깅해보니 이 예제에선 아예 사용되지 않던데
그냥 이렇게 쓰인단걸 알려주시기 위해서 이 강의에 넣으신건가요??
답변 1
5
주말인데도 공부 열심히하시네요 😀
res 는 int * 이런 기본 포인터가 아니에요.
포인터와 비슷한 역할을 하도록 교수님께서 작성하신 AutoPtr 라는 클래스에서 찍어낸 객체일 뿐입니다. 이런 클래스를 그냥 스마트 포인터라고 부르는것 뿐이에요.(뒤에서 배울 C++ 에서 제공하는 스마트 포인터들이 이런식으로 동작한다는 것을 알려주기 위해서 작성하신거에요)
그냥 res 는 객체일 뿐입니다. int * 이런 기본 포인터랑 문법적으로 똑같이 적용될거라고 생각하시면 안됩니다. AutoPtr 은 포인터처럼 동작하게끔하되 좀 편하게 쓰기 위해 교수님께서 만드신 클래스일 뿐이에요. 우리가 여태 코드로 작성한 그런 클래스랑 똑같아요.
그러니까 AutoPtr<Resource>* res = new Resource; 이렇게 res 에 * 를 붙인다면 이건 마치
Base * b, AutoPtr * ptr 이런 느낌인거나 마찬가지에요. 실제 AutoPtr 객체를 만드는 것이 아닌 AutoPtr 객체를 가리키는 포인터를 선언하는거죠.
AutoPtr<Resource>* res = new Resource; 이건 AutoPtr 객체를 가리키는 포인터에 Resource 객체의 주소를 저장하려는 시도이니 아마 컴파일 오류가 날거에요. 타입이 맞지 않으니까요. 마치 int * ptr 에 Resource 객체 주소를 대입하려는거나 마찬가지입니다.
스마트한 포인터로서 써먹기 위해 AutoPtr "객체"를 만드려는건데 이건 심지어 AutoPtr 객체를 만드는 선언도 아닌 AutoPtr 객체를 가리키는 포인터를 만드는 시도입니다. int * ptr 을 선언한다고해서 int 를 가리키는 포인터를 만들어준 것일 뿐이지 int 데이터를 만드는건 아니듯이요.
AutoPtr<Resource> res = new Resource; 는 res 라는 객체가 새롭게 만들어지는 과정이나 마찬가지죠? 그러니 AutoPtr 생성자가 호출되겠네요. AutoPtr(T* ptr = nullptr) 생성자가 호출되고 이 파라미터로 Resource 주소가 들어가겠습니다. 이렇게 AutoPtr 의 멤버인 m_ptr 에서 Resource 객체 주소를 담게 되겠습니다.
이 AutoPtr 클래스를 만든 이유는 포인터처럼 작동시키기 위해 멤버인 m_ptr 에 가리킬 객체를 저장하고 이에 대한 복사와 해제를 스마트하게 하기 위함입니다. AutoPtr(AutoPtr &a) 이건 복사생성자인데 강의에선 안쓰였을지 몰라도 포인터 복사, 즉 소유권 이동을 필수적으로 해주는 작업이 필요하기 때문에 만들어주신거고 스마트 포인터로서 동작하기 위해선 꼭 필요한 부분입니다. 소유권 이동에 대해 덧붙여 말씀드리자면, ptr1 = ptr2 하게되면 ptr1 과 ptr2 가 동일한 객체를 가리키게 되겠죠 둘다? (이러한 상태를 동일한 객체에 대해 두 포인터가 소유권을 가지는 상태라고 할 수 있겠습니다.) 근데 만약 ptr2 이 스코프를 벗어나서 해제되면 해당 객체의 소멸자도 자동으로 호출되게 되므로 객체도 해제될 것입니다. 그럼 졸지에 ptr1 은 이미 해제되어버린 메로리를 가리키게 되겠죠? 이러한 현상을 방지하기 위해서 ptr1 = ptr2 로 ptr2 가 가리키던 객체를 ptr1 에게 소유권을 나눠주었으면 ptr2 는 nullptr 로 초기화시켜주어 해당 객체에 대한 소유권을 해제시켜주어야 합니다.(이 과정은 소유권 박탈과도 같습니다.) 그래야 ptr2 포인터가 영역 벗어나면서 객체를 해제시켜 ptr1 에게 피해를 주는 일이 없기 때문이죠. 아무튼 객체를 가리키는 포인터는 이런 소유권 문제를 신경써주어야 합니다. 그래서 이렇게 포인터처럼 동작하도록 클래스를 만들게 된다면 이런 소유권 이동 문제를 해결하기 위해 복사생성자는 사실상 필수로 직접 작성해 주어야 하는 부분이에요. 이번 강의에선 뭐 안쓰였을 수도 있겠지만요






알아듣기 쉽게 구체적으로 답변해주셔서 감사합니다!!
주말 잘보내세요 :)