[C++] 얇은 복사, 깊은 복사

jh Seo·2022년 11월 2일
1

C++공부

목록 보기
6/21
post-thumbnail

개요

클래스가 다른 클래스를 참조하려할 때, 해당 클래스 안에 참조형식의 멤버 변수가 있다면
얇은 복사인지 깊은 복사인지 방식에 따라 결과값이 달라질수 있다.

얇은 복사

얇은 복사로 클래스를 참조하게 되면 참조형식의 멤버 변수가 있을때 참조값이 복사가 된다.

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>

using namespace std;

class sdp {
public:
	char* name;
	int amount;
	//생성자
	sdp(const char* inputName, int inputAmount)
		:amount(inputAmount)
	{
		name = new char[strlen(inputName)+1];
		strcpy(name,inputName);
	}
	~sdp()
	{
		cout << "소멸자 호출" << '\n';
	}
	//참조값인 name변경되는지 보기위해
	void showInfo() {
		cout << name << " " << amount<<'\n';
	}

};

int main() {
	sdp a("abc", 3);
	sdp b=a;
	a.showInfo();
	b.showInfo();
	strcpy(a.name, "d");
	a.showInfo();
	b.showInfo();

}

이런식으로 c++디폴트 생성자를 사용해 sdp클래스인 b에 a를 참조시켰더니

이런 식으로 a의 이름값만 변경했지만, b의 이름값이 같이 변경되는걸 확인할 수 있었다.

또한 소멸자처리할때

    ~sdp()
	{
		delete[] name;
	}

이런식으로 name값을 delete하게 구현하고 실행해보면 오류가 뜬다.

이유는 a와 b가 같은 곳을 참조하고 있어, 소멸자가 실행될 때 삭제한 메모리를 한번 더 삭제하려고 해서다.

이렇게 참조형식의 멤버변수를 쓸때 얇은 복사만의 특징으로 인해 원하는 결과가 안 나올때
깊은 복사를 사용한다.

깊은 복사

깊은 복사는 참조형식의 멤버 변수값을 복사할 때 같은 메모리의 값을 참조하지 못하도록
복사생성자를 오버라이딩하는 방식이다.

class sdp {
public:
	char* name;
	int amount;
	//생성자
	sdp(const char* inputName, int inputAmount)
		:amount(inputAmount)
	{
		name = new char[strlen(inputName)+1];
		strcpy(name,inputName);
	}
	//복사생성자
	sdp(const sdp& copy)
		:amount(copy.amount) 
	{
		name = new char[strlen(copy.name) + 1];
		strcpy(name, copy.name);
	}
	~sdp()
	{
		delete[] name;
	}
	//참조값인 name변경되는지 보기위해
	void showInfo() {
		cout << name << " " << amount<< '\n';
	}

};

이런식으로 복사생성자를 재정의 해줘서
copy의 name의 길이만큼 할당을 따로한 후 값을 넣어줌으로써 같은 메모리 참조를 방지한다.

이렇게 복사생성자를 재정의해준 후 위 얇은 코드를 재실행 해보면
소멸자에서 오류가 안 나고 정상적으로 실행되며

우리가 의도했던대로 a객체의 name변수만 변경되는 것을 볼 수 있다.

복사생성자엔 보통 const키워드를 사용하는 데
복사하려는 객체의 값을 수정하지 못하도록 하기 위함이다.

생각

만약 복사생성자를

	//복사생성자
	sdp(const sdp& copy)
		:amount(copy.amount) 
	{
		name = new char[strlen(copy.name) + 1];
		strcpy(name, copy.name);
	}

이런식으로 공간 할당후 값을 넣어주는 방식이 아니라

	//복사생성자
	sdp(const sdp& copy)
	{
		name = copy.name;
        amount= copy.amount;
	}

이런 식으로 그냥 넣어준다면 복사생성자를 얇은 복사방식으로 재정의한것이다.

profile
코딩 창고!

0개의 댓글