기계는 거짓말하지 않는다

깊은 복사 / 얕은 복사 본문

C++

깊은 복사 / 얕은 복사

KillinTime 2021. 5. 18. 19:18

class, struct 에 동적 할당하여 사용하는 포인터가 있다면 문제가 될 수 있다.

 

얕은 복사(Shallow Copy)

#include <iostream>
#include <string>

using namespace std;

class A {
private:
	char * str;
	int num;

public:
	A(const char* oStr, int oNum) {
		int len = strlen(oStr) + 1;
		str = new char[len];
		strcpy_s(str, len, oStr);
		num = oNum;
	}

	void PrintData() {
		cout << "str: " << str << endl;
		cout << "num: " << num << endl;
	}

	~A() {
		delete[] str;
		cout << "destructor" << endl;
	}
};

int main() {
	A data1("String1", 100);
	A data2 = data1;	// 포인터가 가르키는 주소가 같음

	data1.PrintData();
	data2.PrintData();
    // 이후 delete 호출
}

 

실행 결과

위 코드는 오류를 일으킨다. 포인터가 같은 주소를 참조하므로 첫 번째 소멸자가 호출 될 때

delete로 메모리 할당 해제 후이기 때문이다.

 

만일 데이터 하나를 변경 한다면 같이 바뀌게 된다.

#include <iostream>
#include <string>

using namespace std;

class A {
private:
	char * str;
	int num;

public:
	A(const char* oStr, int oNum) {
		int len = strlen(oStr) + 1;
		str = new char[len];
		strcpy_s(str, len, oStr);
		num = oNum;
	}

	void PrintData() {
		cout << "str: " << str << endl;
		cout << "num: " << num << endl;
	}

	void ChangeString() {	// 문자 변경
		if(str != NULL)
			str[0] = 'A';
	}

	~A() {
		cout << "destructor" << endl;
	}
};

int main() {
	A data1("String1", 100);
	A data2 = data1;

	data1.PrintData();
	data2.PrintData();

	data1.ChangeString();	// 문자 변경

	data1.PrintData();	// 출력
	data2.PrintData();
}

변경된 결과

이를 얕은 복사(Shallow Copy)라고 한다.

 

깊은 복사(Deep Copy)

복사 생성자를 정의하여 해결할 수 있다.

#include <iostream>
#include <string>

using namespace std;

class A {
private:
	char * str;
	int num;

public:
	A(const char* oStr, int oNum) {
		int len = strlen(oStr) + 1;
		str = new char[len];
		strcpy_s(str, len, oStr);
		num = oNum;
	}

	A(const A& copy) : num(copy.num) {	// 복사 생성자 정의
		int len = strlen(copy.str) + 1;
		str = new char[len];
		strcpy_s(str, len, copy.str);
	}

	void PrintData() {
		cout << "str: " << str << endl;
		cout << "num: " << num << endl;
	}

	void ChangeString() {
		if(str != NULL)
			str[0] = 'A';
	}

	~A() {
		delete[] str;
		cout << "destructor" << endl;
	}
};

int main() {
	A data1("String1", 100);
	A data2 = data1;

	data1.PrintData();
	data2.PrintData();

	cout << "\n변경" << endl;
	data1.ChangeString();

	data1.PrintData();
	data2.PrintData();
	cout << "\n";
}

실행 결과

'C++' 카테고리의 다른 글

C++ 문자열에서 JSON 데이터 파싱(parsing)  (0) 2024.07.30
#ifdef __cplusplus 매크로의 의미  (0) 2024.06.20
vector, priority_queue 정렬 비교  (0) 2021.05.11
Comments