C++ Class ์ Copy Constructor์๋
default copy constructor์ด ์ฌ์ฉํ๋ Shallow Copying๊ณผ Deep Copying์ด ์์ต๋๋ค.
์ผ๋ฐ์ ์ผ๋ก๋ ์์ ๋ณต์ฌ, shallow copying์ ์ฌ์ฉํด๋ ๊ด์ฐฎ์ง๋ง,
์์ ๋ณต์ฌ๊ฐ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํ ๋๊ฐ ์์ต๋๋ค.
์ด๋ฒ ํฌ์คํธ์์๋ ๊ฐ๊ฐ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
Shallow Copying - ์์ ๋ณต์ฌ
Shallow copy๋ ์ปดํ์ผ๋ฌ๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฑํด์ฃผ๋ default copy constructor๊ฐ ํํ๋ ๋ฐฉ๋ฒ์ด๊ธฐ๋ ํฉ๋๋ค.
Shallow copying์ ๋ณต์ฌ ๋์์ ๊ฐ์ฒด์ ๋ชจ๋ ์์ฑ์ ์ง๋ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
์ฌ๊ธฐ์ ์ฃผ์ํด์ผ ํ ์ ์ ํฌ์ธํฐ๊ฐ ๊ฐ์ฒด์์ ์ฌ์ฉ๋ ๋ ์ ๋๋ค.
๋ณต์ฌ์ ๊ณผ์ ์์ ํฌ์ธํฐ๋ ๋ณต์ฌ๋์ง๋ง, ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ์์น, ์ฆ ํฌ์ธํฐ๊ฐ์ ๋ณต์ฌ๊ฐ ์๋ฉ๋๋ค.
(์ฌ๊ธฐ์ ๋ณต์ฌ๋ ๋์ผํ ๊ฐ์ ์ง๋ ์๋ก์ด ๋์์ ์์ฑํ๋ ๊ณผ์ ์ ๋งํฉ๋๋ค.)
๊ทธ๋ ๋ค๋ฉด ๋ญ๊ฐ ๋ฌธ์ ์ผ๊น์?
๋ณต์ฌ ๋์์ ๊ฐ์ฒด A์, ๋ณต์ฌ๋์ด ์์ฑ๋ ๊ฐ์ฒด B๊ฐ ๋์ผํ ๊ฐ์ ๋ค๋ฅธ ํฌ์ธํฐ๋ฅผ ์ง๋๊ณ ์๊ธฐ ๋๋ฌธ์,
๊ฒฐ๊ตญ์๋ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๊ฐ์ ํฌ์ธํ ํ๊ณ ์๋ค๋ ๊ฒ ์ ๋๋ค.
์ฐ๋ฆฌ๋ ๋ ๊ฐ์ฒด์ ๊ฐ์ ๊ฐ์ ๋ค๋ฅธ ์์น๋ก ๋ณต์ฌ๋ฅผ ํ๋ ค๊ณ ํ๋๋ฐ,
์์ ๋์ผํ ์์น์ ์๋ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๊ฒ ๋๋ ๊ฒ์ด์ฃ .
์ฝ๋ ์์
์ด๋ฅผ ์ฝ๋๋ฅผ ํตํด์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ Shallow ํด๋์ค๊ฐ ์กด์ฌํฉ๋๋ค.
// Shallow ํด๋์ค
class Shallow {
private:
int *data; // ์ ์๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
public:
void set_data_value(int val) { *data = val; }
int get_data_value() { return *data; }
// Constructor | ์์ฑ์
Shallow(int d);
// Copy Constructor | ๋ณต์ฌ ์์ฑ์
Shallow(const Shallow &source);
// Destructor | ์๋ฉธ์
~Shallow();
};
์์ฑ์ผ๋ก๋ ์ ์๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ data
๋ฉ์๋๋ก๋ data๋ฅผ ์ง์ ํ๋ set_data_value์, data๋ฅผ ๋ฐํํ๋ get_data_value ๊ฐ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ผ๋ฐ์ ์ธ ์์ฑ์, ๋ณต์ฌ ์์ฑ์์ ์๋ฉธ์๊ฐ ์กด์ฌํฉ๋๋ค.
๊ฐ ๋ฉค๋ฒ์ ๋ํ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Shallow::Shallow(int d) {
data = new int;
*data = d;
}
Shallow::Shallow(const Shallow &source) : data(source.data) {
cout << "Copy Constructor - shalow copy" << endl;
}
Shallow::~Shallow() {
delete data;
cout << "Destructor freeing data" << endl;
}
void display_shallow(Shallow s) { cout << s.get_data_value() << endl; }
์์ฑ์๋ data attribute์ ํ ์์ญ์์ ๋์ ์ผ๋ก ํ ๋นํ ์ ์๋ก ์ ์ธํ๊ณ ,
ํด๋น ์์ญ์ ์์ฑ์์ ์ ๋ ฅ ์ ์ d๋ฅผ ์ ์ฅํฉ๋๋ค.
๋ณต์ฌ ์์ฑ์๋ ์ผ๋ฐ์ ์ธ ํํ ๊ทธ๋๋ก์ด๊ณ , ๋ณต์ฌ ์์ฑ ์ ๋ฌธ๊ตฌ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
์๋ฉธ์๋ ๊ฐ ๊ฐ์ฒด์ data attribute๊ฐ ์์ฑ์ ๋์ ํ ๋น๋๊ธฐ ๋๋ฌธ์ delete ํค์๋๋ก
๋์ ์ผ๋ก ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํด์ค๋๋ค.
๋ง์ง๋ง์ผ๋ก display_shallow๋ ์ ๋ ฅ๋ฐ์ Shallow ๊ฐ์ฒด s์ get_data_value ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ์ถ๋ ฅํฉ๋๋ค.
(get_data_value ๋ฉ์๋๋ data ์ ์ ๊ฐ์ ๋ฐํํด์ค๋๋ค)
๋ง์ง๋ง์ผ๋ก ๋ฉ์ธ ํจ์์ ๋๋ค.
int main(){
Shallow obj1 {100};
display_shallow(obj1);
Shallow obj2 {obj1};
obj2.set_data_value(1000);
return 0;
}
์ฌ๊ธฐ๊น์ง ์ดํด ๋ณด์์ ๋
์ฝ๋์ ๋ฌธ์ ๊ฐ ์์ด ๋ณด์ผ ์ ์์ง๋ง, ์ฌ์ค์ ์ค์ํ ๋ฌธ์ ์ ์ด ์์ต๋๋ค.
obj1 ๊ฐ์ฒด๋ฅผ ์ ์ธํ ๋ค,
display_shallow() ํจ์์ obj1์ ์ธ์๋ก ์คํํ์์ต๋๋ค.
Pass by value ๋ฐฉ๋ฒ์ด๋ฏ๋ก, copy constructor์ ํธ์ถํ์๊ฒ ์ฃ ?
์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
shallow copying์ผ๋ก ์์ฑ๋ ์์ ๊ฐ์ฒด(s)๋ ์๋ณธ ๊ฐ์ฒด์ธ obj1์ data๋ฅผ ๋ณต์ฌํ์ฌ ์์ ์ data ์์ฑ์ผ๋ก ์ผ์ต๋๋ค.
์๋ก์ด ํฌ์ธํฐ์ obj1์ data ์์ฑ๊ฐ์ ์ ์ฅํ๊ฒ ๋๋๋ฐ,
์์ ํ๋ฏ ๋๊ฐ์ง ํฌ์ธํฐ๋ ๋์ผํ ์์น๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์์ต๋๋ค.
ํ์ง๋ง ํจ์ ๋ก์ปฌ ๊ฐ๋ค์ ํจ์ ์คํ์ด ์ข ๋ฃ๋๋ฉด ์ด๋ป๊ฒ ๋์ฃ ?
๋น์ฐํ ๋ฉ๋ชจ๋ฆฌ์์ ์๋ฉธํฉ๋๋ค.
์์๋ก ์์ฑ๋ ๊ฐ์ฒด s๋ display_shallow ํจ์ ์คํ์ด ์ข ๋ฃ๋๋ฉด ๋ฐ๋ก ์ฌ๋ผ์ง๋ฉด์,
์ค์ค๋ก์ ์์ฑ์ธ data ํฌ์ธํฐ์ ์์น๋ฅผ ํด์ ํด๋ฒ๋ฆฝ๋๋ค.
๊ทธ๋ฐ๋ฐ ๊ทธ ์์น๋ ์ฌ์ ํ ์๋ณธ ๊ฐ์ฒด์ธ obj1์ data ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๊ณ ์๋ ์์น์์ฃ ?
๊ทธ๋ผ obj1์ data attribute๋ invalid data๋ฅผ ์ง์นญํ๊ฒ ๋ฉ๋๋ค.
์ฌ๊ธฐ์ ์ฌ์ง์ด Shallow obj2๋ obj1์ ๋ณต์ฌํ์ฌ ์์ฑํ๋ ค๊ณ ํ๊ณ ์์ฃ ?
๊ทธ๋ผ obj2๋ ์ญ์ obj1์ด ๊ฐ๋ฆฌํค๋ invalid data๋ฅผ ์์ฑ์ผ๋ก ์ง๋ ๊ฐ์ฒด๊ฐ ๋๋ ๊ฒ๋๋ค.
๊ทธ ๋ค์์๋ obj2๊ฐ data๋ฅผ 1000์ผ๋ก ๋ฐ๊ฟจ์ฃ ?
๊ทธ๋ผ obj1์ data๋ ๊ฐ์ ๊ฐ์ด๋ฏ๋ก 1000์ผ๋ก ๋ณ๊ฒฝ๋ฉ๋๋ค.
์ด๋ฐ์์ผ๋ก ์ ๋๋ก๋ง ๋ฐ๋๋ค๋ฉด, ์ด์ฉ๋ฉด ์ ํ์ฉํ ์๋ ์์ง ์์๊น์?
๊ทธ๋ ์ง ์์ต๋๋ค.
๊ฐ์ฒด๋ scope๋ฅผ ๋ฒ์ด๋จ๊ณผ ๋์์ ์๋ฉธ์๋ฅผ ํธ์ถํฉ๋๋ค.
๋์ ์ผ๋ก ํ ๋น๋์๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๋ delete๋ฅผ ์ฌ์ฉํ๋๊ฑฐ ๊ธฐ์ต ๋์๋์?
ํ์ง๋ง deleteํ ๊ฐ์ด invalid data์ด๊ธฐ ๋๋ฌธ์,
ํ๋ก๊ทธ๋จ์ ์ถฉ๋ํ๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ๋ฐ์ ์์ต๋๋ค.
์ด๋ค ์์ผ๋ก๋ ์จ๋จน์ ์ ์๊ณ , ๊ทธ์ ์ค๋ฅ์ผ ๋ฟ ์ ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ์กด์ฌํ๋ ๊ฒ์ด ๋ฐ๋ก Deep Copying, ๊น์ ๋ณต์ฌ ์ ๋๋ค.
Deep Copying - ๊น์๋ณต์ฌ
shallow copying์ด ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํ ์์ธ์ด ๋ฌด์์ด์์ฃ ?
ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ด ์๋, ํฌ์ธํฐ ์ฃผ์๊ฐ๋ง ๋ณต์ฌํ๊ธฐ ๋๋ฌธ์ด์์ฃ ?
๊น์ ๋ณต์ฌ๋ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ์ฃผ์์ ๊ฐ ๊น์ง๋ ๋ณต์ฌ๋ฅผ ํฉ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๊น์ ๋ณต์ฌ๋ฅผ ํ ๋์๋ ํ ์์ญ์์ ์๋ก์ด ํฌ์ธํฐ๋ฅผ ์ํ ๋ฐ์ดํฐ๋ฅผ ๋์ ํ ๋นํ๊ฒ ๋ฉ๋๋ค.
์ด๋ฐ ์ด์ ๋ก ๊น์ ๋ณต์ฌ๋ ํด๋์ค์ ๋ฐ์ดํฐ ๋ฉค๋ฒ์ raw pointer๋ฅผ ํฌํจํ๊ณ ์์ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
์์ shallow copying์ ์์ ์ฝ๋์ ๋์ผํ ์์๋ฅผ deep copying์ผ๋ก ํด๊ฒฐํด๋ณด๊ฒ ์ต๋๋ค.
๋ชจ๋ ๊ฒ์ด ๋์ผํ์ง๋ง, ๋ณต์ฌ ์์ฑ์๋ง์ด ๋ค๋ฆ ๋๋ค.
#include <iostream>
#include <string>
using namespace std;
class Deep {
private:
int *data;
public:
void set_data_value(int val) { *data = val; }
int get_data_value() { return *data; }
// Constructor
Deep(int d);
// Copy Constructor
Deep(const Deep &source);
// Destructor
~Deep();
};
Deep::Deep(int d) {
data = new int;
*data = d;
}
// โ๏ธโ๏ธโ๏ธ ๋ณต์ฌ ์์ฑ์ โ๏ธโ๏ธโ๏ธ
Deep::Deep(const Deep &source) {
// โฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธ
data = new int;
*data = *source.data;
// โฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธโฌ๏ธ
cout << "Copy Constructor - deep copy" << endl;
}
Deep::~Deep() {
delete data;
cout << "Destructor freeing data" << endl;
}
void display_deep(Deep s) { cout << s.get_data_value() << endl; }
int main() {
Deep obj1{100};
display_deep(obj1);
obj1.set_data_value(1000);
Deep obj2{obj1};
return 0;
}
ํ์ดํ๋ก ํ์๋ ๋ถ๋ถ์์,
๋ณต์ฌ ์์ฑ์์ ๊ฒฝ์ฐ์๋ ๋์ ์ผ๋ก ์ ์๋ฅผ ํ ๋นํ ๋ค,
ํด๋น ์์ญ์ ์๋ณธ ๊ฐ์ฒด์ data ๋ด๋ถ๊ฐ์ ๋ณต์ฌํ ๊ฒ์ด ๋ณด์ด์๋์?
์๋ก์ด ์์ญ์ ํ ๋นํ๊ณ , ๊ฐ์ ๋ณต์ฌํ ๊ณผ์ ์ ๋๋ค.
ํน์ ํด๋น ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ก๋ ๊ตฌํ ๊ฐ๋ฅํฉ๋๋ค.
Deep::Deep(const Deep &source) : Deep{*source.data} {
cout << "Copy Constructor - deep copy" << endl;
}
์ฌ๊ธฐ๊น์ง ๋ค ์ฝ์ผ์ จ๋ค๋ฉด, ๋์ถฉ ์ฐจ์ด๋ฅผ ์ดํดํ์ จ์ ๊ฒ ๊ฐ์ต๋๋ค.
ํต์ฌ ํฌ์ธํธ๋
'raw pointer๋ฅผ attribute๋ก ์ฌ์ฉํ๋ ํด๋์ค์ ๋ํด์๋ shallow copying์ด ์๋ deep copying์ ์ฌ์ฉํ๋ ๊ฒ'
์ ๋๋ค.
๊น์ ๋ณต์ฌ๋ ๋น์ฐํ ๋์ฑ ๋ณต์กํ๊ณ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ์ก์๋จน์ต๋๋ค.
ํ์ ์๋ ์ํฉ์์๋ ๊น์ ๋ณต์ฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋งค์ฐ ๋นํจ์จ์ ์ด๊ธฐ ๋๋ฌธ์ ์ํฉ์ ๋ง์ถฐ์ ์ ์ ํ๊ฒ ์ฌ์ฉํ ํ์๊ฐ ์๊ฒ ์ต๋๋ค.