복사 생성자(Copy Constructer)

MwG·2024년 11월 17일

C++

목록 보기
4/14

복사 생성자

일반 생성자와 소멸자처럼 복사 생성자라는 것이 존재한다.
말 그대로 객체를 생성할 때 다른 객체를 복사하여 생성한다고 이해하면 된다.



#include <iostream>


class A {


	int a;
	int b;

public:

	A(int x, int y)
	{
		a = x;
		b = y;
	};
	A(const A& sA)
	{
		a = sA.a;
		b = sA.b;
	}

	int Geta() { return a; }
	int Getb() { return b; }

};



int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(NULL);
	std::cout.tie(NULL);
	
	A A1(5,6);
	A A2 = A1;
	A A3(A2);

	std::cout << A1.Geta() << A1.Getb() << std::endl;
	std::cout << A2.Geta() << A2.Getb() << std::endl;
	std::cout << A3.Geta() << A3.Getb() << std::endl;

	return 0;
}

위의 코드를 보게 되면 클래스 A에 대한 객체 A1을 A2에 복사하여 생성하고 A3에 A2를 복사하여 생성되는 것을 알 수 있다. 말 그대로 복사하여 객체를 생성하는 것이다.

이때 const를 붙인 이유는 복사하려는 객체의 데이터를 변경, 업데이트 하려는 것이 아닌 읽기 전용으로 가져오는 것이 때문에 const를 붙였다.

추가로 ref형태로 인자를 받아온 이유는 전체 객체를 class형태로 그대로 받아온다면 인자에 대한 값의 복사를 전부다 처리해야하기 때문에 비효율적이다. 그렇기에 복사할 객체를 가리키는 참조형을 가져옴으로써 좀 더 효율적으로 사용할 수 있게 된다.

디폴트 복사생성자(default)

디폴트 생성자나 소멸자처럼 복사 생성자도 따로 명시하지 않아도


class A {


	int a;
	int b;

public:

	A(int x, int y)
	{
		a = x;
		b = y;
	};


	int Geta() { return a; }
	int Getb() { return b; }

};

결과는 맨 위의 코드와 똑같이 나온다는 것을 확인할 수 있다.

그러면 그냥 굳이 명시하지 않아도 되는거 아닌가? 하는 생각이 들 수 있다.
다음 코드를 보고 생각해보자.


#include <iostream>


class A {


	int a;
	int b;
	int* p;

public:

	A(int x, int y, int n)
	{
		a = x;
		b = y;
		p = new int;
		*p = n;
	};

	~A()
	{
		if (p != nullptr)
			delete p;
	}


	int Geta() { return a; }
	int Getb() { return b; }
	int GetPtr() { return *p; }

};



int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(NULL);
	std::cout.tie(NULL);
	


	A A1(5,6,12);
	A A2 = A1;
	A A3(A2);

	std::cout << A1.Geta() << A1.Getb() << A1.GetPtr() << std::endl;
	std::cout << A2.Geta() << A2.Getb() << A2.GetPtr() << std::endl;
	std::cout << A3.Geta() << A3.Getb() << A3.GetPtr() << std::endl;

	return 0;
}

만약 클래스 내에 동적할당을 통해 값을 받는 경우가 있을 때 A1의 p를 동적할당하고 A2,A3에서 이를 복사하는 것 까지는 괜찮다고 해도 만약 A1이 동적할당을 해제할 경우 A2,A3은 메모리 공간에 없는 변수를 가지고 있는 것이기 때문에 오류가 나게 된다.

얕은 복사(Shallow Copy) , 깊은 복사(Deep Copy)

얕은 복사는 첫부분에 default한 경우에도 가능한 복사를 뜻하고 바로 위의 문제가 발생할 경우엔 직접 복사를 정의하는 깊은 복사를 해야한다.

A(const A& sA)
{
	a = sA.a;
	b = sA.b;

	p = new int;
	*p = *sA.p;
}

이런 식으로 깊은 복사를 하여 해당 오류를 방지할 수 있다.

0개의 댓글