프로그래밍에서 복사는 두 가지 종류가 있다. 하나는 얕은 복사 (shallow copy)
, 다른 하나는 깊은 복사 (deep copy)
이다.
얕은 복사
는 복사 대상이 주소값
이므로 참조하는 값이 서로 같다. 따라서 원본 값이 바뀌면 복사한 값도 바뀐 값을 참조한다.
반면에 깊은 복사
는 서로 다른 독립적인 메모리에 실제 값까지 복사하는 것을 의미한다. 따라서 깊은 복사
에서는 원본 값이 바뀌어도 복사한 값에는 영향이 없다.
깊은 복사
를 반복문으로 직접 구현하면 객체에 포함된 모든 원소를 하나하나 복사하므로 코드도 길고, 양에 따라 오래 걸리 수도 있다. 표준 라이브러리에서는 이를 보완하고자 깊은 복사 함수 copy
를 제공한다.
copy
함수의 원형은 다음과 같다. _First
부터 _Last
전 까지의 모든 원소를 _Dest
부터 시작하는 곳에 복사한다.
template <class _InIt, class _OutIt>
_CONSTEXPR20 _OutIt copy(_InIt _First, _InIt _Last, _OutIt _Dest)
다음 코드는 copy
함수를 활용한 예이다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
struct Person {
string name;
int age;
float height;
float weight;
};
void print_person_all(vector<Person>& people) {
for (vector<Person>::iterator it = people.begin(); it != people.end(); it++) {
cout << "Name: " << it->name << endl;
cout << "Age: " << it->age << endl;
cout << "Height: " << it->height << endl;
cout << "Weight: " << it->weight << endl;
cout << endl;
}
}
int main()
{
Person p[5] = {
{"Alice", 20, 160.0, 50.0},
{"Bob", 25, 172.0, 62.0},
{"Charlie", 30, 183.0, 82.0},
{"David", 35, 191.0, 90.0},
{"Eve", 40, 179.0, 85.0}
};
vector<Person> from_vector;
from_vector.push_back(p[0]);
from_vector.push_back(p[1]);
from_vector.push_back(p[2]);
from_vector.push_back(p[3]);
from_vector.push_back(p[4]);
cout << "----- from_vector -----" << endl;
print_person_all(from_vector);
cout << endl;
// to_vector에 from_vector의 원소를 "깊은 복사" 수행
vector<Person> to_vector;
copy(from_vector.begin(), from_vector.end(), back_inserter(to_vector));
// 복사 후 to_vector 출력
cout << "----- to_vector -----" << endl;
print_person_all(to_vector);
cout << endl;
// from_vector의 첫 번째 원소 수정
from_vector[0].name = "Alice2";
from_vector[0].age = 21;
from_vector[0].height = 161.0;
from_vector[0].weight = 51.0;
// 수정 후 from_vector 출력
cout << "----- from_vector -----" << endl;
print_person_all(from_vector);
cout << endl;
// to_vector 출력
cout << "----- to_vector -----" << endl;
print_person_all(to_vector);
cout << endl;
return 0;
}
실행 결과
----- from_vector -----
Name: Alice
Age: 20
Height: 160
Weight: 50
Name: Bob
Age: 25
Height: 172
Weight: 62
Name: Charlie
Age: 30
Height: 183
Weight: 82
Name: David
Age: 35
Height: 191
Weight: 90
Name: Eve
Age: 40
Height: 179
Weight: 85
----- to_vector -----
Name: Alice
Age: 20
Height: 160
Weight: 50
Name: Bob
Age: 25
Height: 172
Weight: 62
Name: Charlie
Age: 30
Height: 183
Weight: 82
Name: David
Age: 35
Height: 191
Weight: 90
Name: Eve
Age: 40
Height: 179
Weight: 85
----- from_vector -----
Name: Alice2
Age: 21
Height: 161
Weight: 51
Name: Bob
Age: 25
Height: 172
Weight: 62
Name: Charlie
Age: 30
Height: 183
Weight: 82
Name: David
Age: 35
Height: 191
Weight: 90
Name: Eve
Age: 40
Height: 179
Weight: 85
----- to_vector -----
Name: Alice
Age: 20
Height: 160
Weight: 50
Name: Bob
Age: 25
Height: 172
Weight: 62
Name: Charlie
Age: 30
Height: 183
Weight: 82
Name: David
Age: 35
Height: 191
Weight: 90
Name: Eve
Age: 40
Height: 179
Weight: 85
copy
함수가 깊은 복사를 하는지 직접 확인하고자 이름을 비롯해 여러 원소를 가진 Person 구조체의 객체들을 벡터 컨테이너에 저장했다.
실행 결과에서 to_vector
로 표시한 부분을 보면 Person
구조체의 모든 원소가 완전히 복사된 것을 확인할 수 있다. 또한 to_vector
에 복사한 후 from_vector
의 첫 번째 값을 변경해도 to_vector
에 저장된 원소에는 전혀 영향이 없음을 확인할 수 있다. 즉, from_vector
와 독립적으로 깊은 복사가 수행된 것이다.
이처럼 여러 개의 원소를 깊게 복사해야 한다면 표준 라이브러리의 copy
함수를 적극 활용하자. 코드가 간결해질 뿐만 아니라 성능까지 확보할 수 있다.