티스토리 뷰
05-1 복사 생성자는 왜 필요한가?
C++ 스타일의 초기화
int num=20;
int &ref=num;
우리는 이렇게 초기화했지만 다음 방법도 가능하다.
int num(20);
int &ref(num);
class SoSimple
{
private:
int num1;
int num2;
};
SoSimple=sim1;
SoSimple sim2=sim1;
sim2 num1 <- sim1 num1
sim2 num2 <- sim1 num2
SoSimple sim2(sim1);
이 문장에 담겨 있는 의미를 생각해보자.
SoSimple형 객체를 생성해라.
객체의 이름을 sim2로 정한다.
sim1을 인자로 받을 수 있는 생성자의 호출을 통해 객체생성을 완료한다.
복사생성자는 호출시점이 일반 생성자와 차이가 있다.
-> 호출시점을 잘 아는 게 중요하다.
자동으로 삽입이 되는 디폴트 생성자
'복사 생성자를 정의하지 않으면, 멤버 대 멤버 복사를 진행하는 디폴트 복사 생성자가 자동으로 삽입된다.'
변환에 의한 초기화! 키워드 explicit으로 막을 수 있다.
SoSimple sim2=sim1;
이 경우 묵시적 변환이 일어나서 복사 생성자가 호출된다.
explicit Sosimple(const SoSimple ©)
:num1(copy.num1), num2(copy.num2)
{
//empty!
}
더 이상 묵시적 변환이 발생하지 않아서 대입 연산자를 이용한 객체의 생성 및 초기화는 불가능하다.
AAA obj=3; //AAA obj(3); 으로 변환
explicit이 있을 경우
AAA obj(3);
-> 이 형태로만 객체 생성을 할 수 있다.
참고 복사 생성자의 매개변수는 반드시 참조형이어야 하는가?
05-2 '깊은 복사'와 '얕은 복사'
디폴트 복사 생성자의 문제점
#include <iostream>
#include <cstring>
using namespace std;
class Person
{
private:
char* name;
int age;
public:
Person(char* myname, int myage)
{
int len = strlen(myname) + 1;
name = new char[len];
strcpy(name, myname);
age = myage;
}
void ShowPersonInfo() const
{
cout << "이름: " << name << endl;
cout << "나이: " << age << endl;
}
~Person()
{
delete[]name;
cout << "called destructor!" << endl;
}
};
int main(void)
{
Person man1("Lee dong woo", 29);
Person man2 = man1;
man1.ShowPersonInfo();
man2.ShowPersonInfo();
return 0;
}
called destructor! 가 두번 호출 되어야 하는데 한 번만 호출된다.
man1 -> Lee dong woo <-man2
둘다 같은 Lee dong woo를 참조하고 있다가, Lee dong woo가 삭제되기 때문에 문제가 발생한다.
그렇기에 man2가 참조하던 문자열도 없어진다.
'깊은 복사'를 위한 복사 생성자의 정의
Person(const Person& copy):age(copy.age)
{
name=new char[strlen(copy.name)+1];
strcpy(name,copy.name);
}
멤버 변수 age의 멤버 대 멤버 복사
메모리 공간 할당후 문자열 복사, 그리고 할당된 메모리의 주소 값을 멤버 name에 저장
05-3 복사생성자의 호출시점
복사 생성자가 호출되는 시점은?
case 1: 기존에 생성된 객체를 이용하여 새로운 객체를 초기화하는 경우(앞서 보인 경우)
case 2: call-by-value 방식의 함수호출 과정에서 객체를 인자로 전달하는 경우
case 3: 객체를 반환하되, 참조형으로 반환하지 않는 경우
공통점
객체를 새로 생성해야 한다. 단 생성과 동시에 자료형의 객체로 초기화해야한다.
메모리 공간의 할당과 초기화가 동시에 일어나는 상황
매개변수 호출 시 메모리 할당
반환시 메모리 할당
할당 이후 복사생성자를 위한 통한 초기화
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
class Temporary
{
private:
int num;
public:
Temporary(int n) : num(n)
{
cout << "create obj: " << num << endl;
}
~Temporary()
{
cout << "destroy obj " << num << endl;
}
void ShowTempInfo()
{
cout << "My num is " << num << endl;
}
};
int main(void)
{
Temporary(100);
cout << "*********** after make!" << endl << endl;
Temporary(200).ShowTempInfo();
cout << "************* after make!" << endl << endl;;
const Temporary& ref = Temporary(300);
cout << "***************** end of main!" << endl<<endl;
return 0;
}
after make란 말이 나오기 전에 이미 소멸한 것을 보여준다.
-임시객체는 다음 행으로 넘어가면 바로 소멸되어 버린다.
-참조자에 참조되는 임시객체는 바로 소멸되지 않는다.
05-4 OOP 단계별 프로젝트 03단계
'프로그래밍 > 윤성우의 열혈 C++' 카테고리의 다른 글
Chapter 07 상속(Inheritance)의 이해 (0) | 2022.03.09 |
---|---|
Chapter 06 friend와 static 그리고 const (0) | 2022.03.08 |
Chpater 04 클래스의 완성 (0) | 2022.03.05 |
Chapter 03 클래스의 기본 (0) | 2022.03.04 |
Chapter 02 C언어 기반의 C++ 2 (0) | 2022.03.04 |
- Total
- Today
- Yesterday
- 일문따
- 티스토리챌린지
- 통계
- Python
- 사회심리학
- C/C++
- 인프런
- 오블완
- 일본어
- stl
- 보세사
- 회계
- 류근관
- 열혈프로그래밍
- 윤성우
- 백준
- 파이썬
- 데이터분석
- 통계학
- 인지부조화
- 코딩테스트
- jlpt
- K-MOOC
- 여인권
- EBS
- C
- c++
- 일본어문법무작정따라하기
- 뇌와행동의기초
- 심리학
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |