C++ 복사 생성자의 얕은 복사 과정 ?
조회수 855회
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass()
{
pnumber = new int(5);
}
~MyClass()
{
delete pnumber;
}
int number = 0;
int *pnumber = nullptr;
};
int main()
{
MyClass a;
a.number = 300;
cout << "a.n의 값 " << a.number << endl;
cout << "a.pn의 값 " << *a.pnumber << endl;
cout << "a.pn의 주소값 " << a.pnumber << endl;
MyClass b(a);
cout << "b.n의 값 " << b.number << endl;
cout << "b.pn의 값 " << *b.pnumber << endl;
cout << "b.pn의 주소값 " << b.pnumber << endl;
a.number = 400;
return 0;
}
아직 학부생이라 정확히 어떻게 질문을 해야할 지 몰라서 제목 및 질문이 좀 난해한 점 사과드립니다.
위 코드에서 인스턴스 b는 디폴트 복사 생성자를 통해 a를 복사하는데, 이 때 제가 배운 바로는
디폴트 복사 생성자는 얕은 복사기 때문에 그림과 같이 b.pnumber 변수는 a.pnumber가 가리키는 new int(5)를 가리키는 형태로 복사가 된다.
이 때 소멸자에 delete pnumber 가 포함되어 있으므로 이미 해제된 메모리(빨간 화살표)를 다시 해제하는 꼴이 되어 에러가 발생한다.
이렇게 알고있습니다.
여기서 궁금한 점은
a.pnumber는 생성자의 pnumber = new int(5) 코드를 통해 명백하게 할당을 받게 되는데, 복사 생성자로 생성된 b.number는 (복사 생성자로 그림과 같이 되기 이전에) 과연 할당을 받는가? 받는다면 어떠한 과정을 통해 언제 받게 되는가? 에 대한 것입니다.
에러가 발생했을 때
(1) b.pnumber가 new int(5) (빨간화살표)를 할당받음 -> 얕은 복사로 인한 메모리 (빨간화살표) 해제 -> 이미 해제된 영역을 소멸자 코드가 다시 해제를 요청하여 에러 발생
(2) b.pnumber는 생성과 동시에 a.pnumber를 얕은 복사함 -> 새로이 할당받은 적이 없음 -> 애초에 할당받지 못한 영역을 소멸자 코드가 해제 요청하여 에러 발생
이 둘 중 어떤 과정이 맞는 것인지 궁금합니다.
책이나 강의 등에서는 모두 (1)과 같이 얕은 복사 이전에 이미 어느 시점엔가 b.pnumber는 할당을 받았다는 전제가 깔리던데 이에 대한 설명은 따로 없어서 질문 드렸습니다.
감사합니다.
-
(•́ ✖ •̀)
알 수 없는 사용자
1 답변
-
기본 복사 생성자는 아마 그냥 복사만 할 겁니다. 그게 포인터더라도요.
컴파일러는 포인터가 가리키고 있는 게 하나여야 하는지, 둘이어야 하는지 모르니까 (이건 프로그래머가 결정할 문제니까) 그냥 주소만 복사를 해버리거든요...
그래서
b.pnumber
는 할당을 받는 게 아니라a.pnumber
를 복사합니다. 즉, 복사 생성자에서는b.pnumber = a.pnumber
가 일어납니다.b.pnumber
에 대한new
는 어디에서도 일어나지 않습니다.&(a.pnumber)
가0x20180419
였다면&(b.pnumber)
도0x20180419
이고, 이는 A의 생성자에서 실행된new int(5)
라는 수식이 반환한 주소인0x20180419
와 같습니다. 메모리 위치0x20180419
에 있는 정수는 하나인데 정작 복사되는 건 메모리 위치를 가리키는 숫자인0x20180419
뿐인 거죠.C / C++에서 포인터의 얕은 복사란 그저 주소값을 그대로 복사하는 것을 의미합니다. 주소도 정수값이니까요.
(2) 가 정답처럼 보이네요.
댓글 입력