본문 바로가기
프로그래밍 언어/C++

[C++] 얕은 복사 (Shallow Copy)

by 까망 하르방 2025. 3. 13.
반응형

얕은 복사 (Shallow Copy)

• 메모리 자체를 복사 하지 않고 주소만 복사

• 일반적으로 「=」 연산자가 해당

 

 

[예제] 복사성생자 & 대입 연산자

#include <iostream>

class Point
{
	int x = 0;
	int y = 0;

public:
	Point() = default;
	Point(int x, int y) : x{ x }, y{ y } {}
};

int main()
{
	Point p1{ 1, 1 };

	Point p2 = p1; // 복사 생성자

	p2 = p1; // 대입 연산자
}



Point 클래스 안에 x, y 는 각각 매핑되어 값이 복사되어 진다.
• 복사 생성자 = 객체 생성하면서 초기화
• 대입 연산자 = 객체 생성 후 넣는 것
 (사용자가 만들지 않으면 컴파일러가 디폴트 복사 생성자 제공)

이러한 복사생성자/대입 연산자는 Primitive 타입에서는 괜찮지만
특정 특정 클래스에서는 문제 될 수 있다.


[예제] 복사 생성자의 얕은 복제

#include <iostream>

class vector
{
	int* ptr;
	std::size_t sz;

public:
	vector(std::size_t sz, int value = 0) : sz(sz)
	{
		ptr = new int[sz];

		for (std::size_t i; i < sz; i++)
		{
			ptr[i] = value;
		}
	}
	~vector() { delete[] ptr; }
};

int main()
{
	vector v1(5);

	vector v2 = v1; // 복사 생성자 -> ??
}



vector v2 = v1; 에서
v2는 v1의 ptr, sz가 복사된다.

이때 배열을 가리키는 ptr 에 대해 생각해보면
배열 자체를 복사하는 것이 아니라 배열을 가리키는 포인터가 복사된다.
결과적으로 v1.ptr 과 v2.ptr은 동일한 배열을 가리키고 있다.


이 경우

• v1, v2 중 한쪽에서 변경하면 다른쪽도 같이 변경된다.

• 한쪽이 소멸되면 다른쪽도 더 이상 사용할 수 없다.

 

클래스 내부에 포인터 멤버가 있고

힙 메모리 등 자원을 사용한다면

컴파일러가 제공하는 대입 연산자는 얕은 복사 현상을 일으킨다.

그렇기에 사용자가 직접 복사 생성자(대입연산자)를 만드는 것이 좋다.


얕은 복사 해결 방법

• 깊은 복사 (Deep Copy)

• 복사 및 대입 금지 (= delete)

• 참조 계수 (Reference Counting)

• 소유권 이전

반응형

댓글