복사 생성자란?
변수와 참조자를 다음과 같이 선언, 초기화 할 수 있는 것처럼
int num = 20;
int &ref = num;
int num(20);
int &ref(num);
객체또한 다음과 같은 방법으로 선언, 초기화할 수 있다.
Simple sim1(10, 20);
Simple sim2 = sim1;
Simple sim3(10, 20);
Simple sim4(sin3);
이 때 실행되는 생성자를 '복사 생성자'라고 한다.
+ Simple sim2 = sim1; 과 같이 초기화하는 것을 막으려면 복사생성자 앞에 explicit 키워드를 이용함으로써 막을 수 있다.
- 복사생성자는 따로 정의가 되어있지 않으면 디폴트 복사 생성자가 자동으로 삽입된다.
Simple
{
private:
int num1;
int num2;
public:
Simple(int n1, int n2):num1(n1), num2(n2) { }
Simple(const Simple& copy) : num1(copy.num1), num2(copy.num2) { }
}
따라서 많은 경우에 복사 생성자를 따로 정의하지 않아도 된다.
다만 멤버변수에 동적할당을 한 포인터가 있다면 복사 생성자를 따로 정의해야될 필요가 생긴다.
만일 동적할당을 해놓은 객체를 복사한다면 '디폴트 복사 생성자'가 복사하는 것은 값 그대로를 복사하기 때문에 다른 객체에 같은 주소값을 가진 멤버변수가 존재하게 된다.
그리고 소멸자가 호출되면 메모리의 해제를 진행하기 때문에 두 개의 객체중 하나의 객체만 소멸되면 다른 객체에도 영향을 주게된다.
깊은 복사
이를 막기위해 '깊은 복사'를 위한 복사 생성자를 정의한다.
Simple(const Simple& copy): num(copy.num)
{
name = new char[strlen(copy.name)+1];
strcpy(name, copy.name);
}
메모리 공간의 할당과 초기화
함수를 호출할때 매개변수의 메모리 공간이 할당되고 전달되는 인자를 통해 초기화 된다.
함수에서 어떤 값을 반환할때도 메모리 공간이 할당되면서 동시에 초기화 된다.
객체를 매개변수로 전달된다면 매개변수의 메모리 공간에 초기화 될때 복사 생성자가 호출된다.마찬가지로 객체를 반환할때도 복사생성자가 호출된다.
#include <iostream>
using namespace std;
class Simple
{
private:
int num;
public:
Simple(int n) :num(n)
{
cout << "New object: " << this << endl;
}
Simple(const Simple& copyObj) :num(copyObj.num)
{
cout << "New Copy obj: " << this << endl;
}
~Simple()
{
cout << "Destroy obj: " << this << endl;
}
};
Simple SimpleFuncObj(Simple ob)
{
cout << "Parm ADR: " << &ob << endl;
return ob;
}
int main()
{
Simple obj(7);
SimpleFuncObj(obj);
cout << endl;
cout << "tempRef1" << endl;
Simple tempRef1 = SimpleFuncObj(obj);
cout << endl;
cout << "tempRef2" << endl;
const Simple &tempRef2 = SimpleFuncObj(obj);
cout << endl;
cout << "tempRef3" << endl;
const Simple &tempRef3 = tempRef1;
cout << endl;
cout << "&tempRef1: " << &tempRef1 << endl;
cout << "&tempRef2: " << &tempRef2 << endl;
cout << "&tempRef3: " << &tempRef3 << endl;
return 0;
}
위 코드를 통해서 흐름을 배울 수 있다.
궁금한 점
Simple tempRef1 = SimpleFuncObj(obj);
const Simple &tempRef2 = SimpleFuncObj(obj);
1. 두 개가 같은 방식으로 동작하는데 차이점이 존재하는가?
2. 차이점이 존재하지 않는다면 일반적으로 쓰이는 방법은 무엇인가?
'프로그래밍 언어 > 열혈 C++' 카테고리의 다른 글
07 상속의 이해 by 윤성우의 열혈 C++ (0) | 2022.03.08 |
---|---|
06 const, friend, static, mutable by 윤성우의 열혈 C++ (0) | 2022.03.07 |
04-4 클래스와 배열 그리고 this 포인터 by 윤성우의 열혈 C++ (0) | 2022.03.05 |
04-3 생성자와 소멸자 by 윤성우의 열혈 C++ (0) | 2022.03.04 |
Chapter 04-2 캡슐화 by 윤성우의 열혈 C++ (0) | 2022.03.03 |