복사생성자 함수란?
1. 필드 '값'을 모두 복사하는 것입니다.
2. 기본적으로 얕은 복사를 제공합니다.
3. 깊은 복사는 기본적으로 제공하지 않기 때문에 개발자가 필요에 의해
제공해야합니다
==예시==
A(const A & aa){ //const를 써주는 이유는 복사할 대상의 값이 변경되면 안되기 때문
a = aa.a;
b = aa.b;
} //디폴트 기능(얕은 복사)
==복사생성자의 호출 시기==
1) 객체 생성시 객체를 인자로 줄 겨우
A aa; //생성자 호출
A bb(aa); //복사생성자 호출
2) 객체 생성시 객체를 대입할 경우
A aa; //생성자 호출
A aa = bb //복사생성자 호출
3) member function의 매개변수로 객체를 선언할 경우
void A : : disp(A aa)
4) 멤버함수에서 객체를 리턴할 경우
A getObject( )
{
return 객체; //복사생성자 호출
}
===========================
얕은 복사란?
=>명시적으로 만들지 않았을 때 기본적으로 제공되는 복사입니다.
1. (얕은 복사 예제 코드)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 |
#include<iostream>
using namespace std;
class A
{
int a;
int b;
public :
A(int a = 0, int b = 0) // C++에서 this 는 포인터, method 안의
//instance method 안에 있다.(this 선언할 수 없음, 항상 존재) {
this->a = a;
this->b = b;
}
A(const A & aa) { //복사생성자 ==> 명시적으로 만들면 디폴트기능이 없어짐.
cout << "복사생성자" << endl;
a = aa.a;
b = aa.b;
} //디폴트 기능(얕은 복사)
void setA(int a) {
this->a = a;
}
void setB(int b){
this->b = b;
}
int getA() {
return a;
}
int getB() {
return b;
}
};
void main()
{
A bb(10, 20);
A aa;
cout << aa.getA() << "\t" << aa.getB() << endl; // 0, 0
cout << bb.getA() << "\t" << bb.getB() << endl; // 10, 20
cout << "\n";
A cc(bb); //복자생성자호출
cout << cc.getA() << "\t" << cc.getB() << endl; // bb값을 전체 카피
} |
cs |
※얕은 복사는 명시적으로 만들면 디폴트 기능이 없어집니다.
(실행 결과)
===========================
깊은 복사란?
=> 필요에 의해 개발자가 직접 복사생성자함수를 만들어 사용하는 것.
2. (깊은 복사 예제 코드)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 |
#include<iostream>
using namespace std;
class A
{
int *p;
public:
A(int i = 0)
{
p = new int;
*p = i;
}
/*
A(const A& aa)
{
p= aa.p;
} //복사생성자 default 모양
*/
A(const A& aa)
{
p = new int;
*p = *aa.p;
}
~A() {
//cout << *p << endl;
delete p;
}
int getP(){
return *p;
}
};
void main() { //정적메모리 stack구조 FILO(First In Last Out)
A aa(10);
//A bb(20);
A bb(aa); //복사생성자 호출
cout << bb.getP() << endl;
} |
cs |
※ 만약 깊은 복사를 하지 않게 된다면, 런타임 오류가 발생하게 됩니다.
현재 생성자를 포인터형식으로 만들었습니다.
메인함수에서 A aa(10)을 호출하게 되면 힙(heap)영역에 10이라는 공간을 가리키는 포인터가 만들어집니다.
그 후, A bb(aa)에서 복사생성자를 호출하게 되는데 이 때 힙(heap)영역의 10의 값을 복사하는게 아니고 10공간의 주소를 복사하게 되어 힙(heap)영역의 10의 공간을 같이 가리키게 됩니다. 그 후, 메인이 끝나며 메모리가 제거되는데 스택(FILO=>First In Last Out)에 의해 a bb(aa)부터 메모리를 해제하게 됩니다. 이 때, 먼저 10의 공간을 삭제해버리게 되고, A aa(10)의 메모리를 해제하려는데 이미 A bb(aa)에서 가리키는 곳을 지웠기 때문에, A aa(10)이 지울 공간이 사라져 런타임 오류가 발생하게 됩니다.
(실행 결과)
※ 필드를 포인터로 써줬을 경우엔 !반드시! 깊은 복사를 해야합니다. 그렇지 않으면 runtime 오류가 발생합니다.
'Programming > C++' 카테고리의 다른 글
(C++)난 private고 넌 외부사람이야! 우린 안돼! 접근지정자에 대해 알아보자! (0) | 2018.03.09 |
---|---|
(C++) 클래스를 이용하여 성적처리 (4) | 2018.03.08 |
(C++) 생성자 함수란 무엇일까? (0) | 2018.03.08 |
(C++) 성적 입/출력 다차원 프로그램 (0) | 2018.03.07 |
(C++) 오버로딩(overloading)이란?? (0) | 2018.03.07 |