반응형

오랜 시간 미뤄온 c, c++ 언어 학습 내용을 티스토리에 차근차근 업로드하려고 한다.

 

먼저 구조체 관점에서의 얕은 복사, 깊은 복사가 어떤 차이점이 있을까?

 

  1. 얕은 복사
#include <iostream>
#include <cstring>

using namespace std;

typedef struct Student
{
	float height;
	char* name;
} Student;

int main() {
	
	Student alice, bob;
	char alice_s[] = "alice";
	char bob_s[] = "bob";
	
	alice.name = alice_s;
	alice.height = 160;
	bob.name = bob_s;
	bob.height = 170;

	bob = alice;

	printf("alice name: %s, height: %lf\n", alice.name, alice.height);
	printf("bob name: %s, height: %lf\n", bob.name, bob.height);
	return 0;
}

 

학생들의 키 정보를 가진 구조체를 생성하고 alice, bob 이라는 학생 구조체를 선언했다. 그리고 이름과 키 정보를 저장하고 있는 alice의 정보를 bob 구조체에 복사하려고 한다.

 

= 을 이용하여 bob 구조체 주소에 alice의 구조체 주소를 복사하니 bob 구조체에는 alice의 정보들이 담겼다. 

alice name: alice, height: 160.000000
bob name: alice, height: 160.000000

 

하지만 얕은 복사 시 주의해야 할 점이 있다.

만약 alice의 이름을 chris 수정했다고 해보자.

#include <iostream>
#include <cstring>

using namespace std;

typedef struct Student
{
	float height;
	char* name;
} Student;

int main() {
	
	Student alice, bob;
	char alice_s[] = "alice";
	char bob_s[] = "bob";
	
	alice.name = alice_s;
	alice.height = 160;
	bob.name = bob_s;
	bob.height = 170;

	bob = alice;
	/*printf("address: %p, %p\n", bob, alice);*/
	printf("name address: %p, %p\n", bob.name, alice.name);
	printf("height address: %p, %p\n", bob.height, alice.height);

	printf("alice name: %s, height: %lf\n", alice.name, alice.height);
	printf("bob name: %s, height: %lf\n", bob.name, bob.height);

	strcpy(alice.name, "chris");

	printf("<after mod> alice name: %s, height: %lf\n", alice.name, alice.height);
	printf("<after mod> bob name: %s, height: %lf\n", bob.name, bob.height);
	return 0;
}
name address: 0x7ffdbbdd1992, 0x7ffdbbdd1992
height address: 0x622e4bab02b0, (nil)
alice name: alice, height: 160.000000
bob name: alice, height: 160.000000
<after mod> alice name: chris, height: 160.000000
<after mod> bob name: chris, height: 160.000000

 

구조체의 얕은 복사 결과 alice와 bob의 이름 변수의 주소가 동일해졌고 alice의 이름을 chris로 바꾸니 bob의 이름도 chris가 되어버렸다. 구조체 내의 포인터 변수인 이름 멤버 변수가 값을 복사하지 않고 alice의 이름 주소값을 복사해옴으로써 발생한 문제점이다. 

 

그렇다면, 위의 문제를 해결하려면 어떻게 해야 할까?

 

반응형

 

  2. 깊은 복사

#include <iostream>
#include <cstring>

using namespace std;

typedef struct Student
{
	float height;
	char* name;
} Student;

int main() {
	
	Student alice, bob;

	alice.name = (char*)malloc(sizeof(char) * 30);
	bob.name = (char*)malloc(sizeof(char) * 30);

	strcpy(alice.name, "alice");
	alice.height = 160;
	strcpy(bob.name, "bob");
	bob.height = 170;

	bob.height = alice.height;
	strcpy(bob.name, alice.name);

	printf("address: %p, %p\n", bob, alice);
	printf("name address: %p, %p\n", bob.name, alice.name);
	printf("height address: %p, %p\n", bob.height, alice.height);
	
	printf("alice name: %s, height: %lf\n", alice.name, alice.height);
	printf("bob name: %s, height: %lf\n", bob.name, bob.height);

	strcpy(alice.name, "chris");

	printf("<after mod> alice name: %s, height: %lf\n", alice.name, alice.height);
	printf("<after mod> bob name: %s, height: %lf\n", bob.name, bob.height);
	free(alice.name);
	free(bob.name);
	return 0;
}
address: 0x65395ed082e0, 0x65395ed082b0
name address: 0x65395ed082e0, 0x65395ed082b0
height address: 0x65395ed08310, (nil)
alice name: alice, height: 160.000000
bob name: alice, height: 160.000000
<after mod> alice name: chris, height: 160.000000
<after mod> bob name: alice, height: 160.000000

 

Student 구조체의 멤버 변수로 포인터 변수를 그대로 사용하려면 메모리 동적 할당해주고 하나하나 복사하면 된다.

또 다른 방법으로는 이름 멤버 변수를 배열로 바꾸고 하나하나 복사하면 된다. 

 

이런 개념은 확실하게 알아둬야 나중에 고생하지 않는다...!

반응형

+ Recent posts