C, C++
29. 복사 생성자
Yongs12
2023. 6. 19. 23:38
C++에서 복사 생성자는 동일한 클래스의 기존 객체 복사본으로 새 객체를 만드는 데 사용되는 유형의 생성자이다.
이때 깊은 복사(Deep Copy)와 얕은 복사(Shallow Copy)의 개념이 등장한다.
Shallow Copy(얕은 복사) 예시
int main()
{
int* pA = new int(5);
int* pB = nullptr;
// Shallow Copy(얕은 복사)
pB = pA;
delete pA;
// 얕은 복사를 한 경우 pA를 지우면 pB는 pA를 가리키고 있는 포인터일 뿐이기에
// 삭제된 데이터를 지우려고 하기에 에러가 뜬다.
delete pB;
return 0;
}
Deep Copy(깊은 복사) 예시
int main()
{
int* pA = new int(5);
// 그대로 복사가 아닌 새롭게 메모리를 할당해준다.
int* pB = new int(*pA);
delete pA;
delete pB;
return 0;
}
복사 생성자 예시
#include <iostream>
class CTest
{
public:
CTest()
{
std::cout << "CTest() 생성자 호출" << std::endl;
}
~CTest()
{
std::cout << "~CTest() 소멸자 호출" << std::endl;
}
};
int main()
{
CTest a;
// 복사 생성자 호출 컴파일러가 자동으로 생성
CTest b(a);
return 0;
}
복사 생성자는 컴파일러가 아닌 본인이 직접 만들어야 할 때가 있는데
포인터를 사용할 경우 만들어줘야 한다.
#include <iostream>
class CTest
{
// 포인터 변수를 사용할 시
int* pA;
public:
CTest()
{
std::cout << "CTest() 생성자 호출" << std::endl;
pA = new int;
}
~CTest()
{
std::cout << "~CTest() 소멸자 호출" << std::endl;
delete pA;
}
};
int main()
{
CTest a;
// 복사 생성자 호출
CTest b(a);
return 0;
}
위와 같이 포인터 변수에 메모리 동적할당을 할 경우 원본 객체와 복사 생성된 객체에서 둘 다 소멸자 호출 시 동적 할당된 메모리를 해제하기 때문에 Error가 발생한다.
동적 할당된 객체를 복사할 경우 새롭게 메모리를 동적 할당 해야 한다.
#include <iostream>
class CTest
{
int* pA;
public:
CTest()
{
std::cout << "CTest() 생성자 호출" << std::endl;
pA = new int;
}
// 직접 복사 생성자를 만들어 준다. 이 때 const 키워드를 쓰는 이유는
// 원본을 변경안하고 읽어들이기만 하기 위해서다.
CTest(const CTest& _pA)
{
std::cout << "CTest(CTest& _pA) 복사 생성자 호출" << std::endl;
// 복사되는 객체에 새롭게 메모리를 동적 할당해주어야 한다.
this->pA = new int(*_pA.pA);
}
~CTest()
{
std::cout << "~CTest() 소멸자 호출" << std::endl;
delete pA;
}
};
int main()
{
CTest a;
CTest b(a);
return 0;
}