1. 객체 전달과 참조
1) '값에 의한 호출'로 객체 전달
- 함수를 호출하는 쪽에서 객체 전달
- 객체 이름만 사용
- 함수의 매개 변수 객체 생성
- 매개 변수 객체의 공간이 스택에 할당
- 호출하는 쪽의 객체가 매개 변수 객체에 그대로 복사됨
- 매개 변수 객체의 생성자는 호출되지 않음
- 함수 종료
- 매개 변수 객체의 소멸자 호출
▶값에 의한 호출 기 매개 변수 객체의 생성자가 실행되지 않는 이유?
-호출되는 순간의 실인자 객체 상태를 매개 변수 객체에 그대로 전달하기 위해


2) '주소에 의한 호출'로 객체 전달
- 함수 호출 시 객체의 주소만 전달
- 함수의 매개 변수는 객체에 대한 포인터 변수로 선언
- 함수 호출 시 생성자, 소멸자가 실행되지 않는 구조

3) 객체 치환 및 객체 리턴
- 객체 치환
- 동일한 클래스 타입의 객체끼리 치환 가능
- 객체의 모든 데이터가 비트 단위로 복사
- 치환된 두 객체는 내용만 같을 뿐 독립적인 공간 유지
Circle c1(5);
Circle c2(30);
c1 = c2; // c2 객체를 c1 객체에 비트 단위 복사. c1의 반지름 30됨
- 객체 리턴
#include <iostream>
using namespace std;
class Circle {
int radius;
public:
Circle() { radius = 1; }
Circle(int radius) { this->radius = radius; }
void setRadius(int radius) { this->radius = radius; }
double getArea() { return 3.14*radius*radius; }
};
Circle getCircle()
{
Circle tmp(30);
return tmp; // 객체 tmp을 리턴한다.
}
int main()
{
Circle c; // 객체가 생성된다. radius=1로 초기화된다.
cout << c.getArea() << endl;
c = getCircle(); // tmp 객체가 c에 복사됨, c의 radius 값이 30이 됨
cout << c.getArea() << endl;
}

- 객체에 대한 참조
#include <iostream>
using namespace std;
class Circle {
int radius;
public:
Circle() { radius = 1; }
Circle(int radius) { this->radius = radius; }
void setRadius(int radius) { this->radius = radius; }
double getArea() { return 3.14 * radius * radius; }
};
int main() {
Circle circle;
Circle& refc = circle; //circle객체에 대한 Circle형 참조 변수 refc 선언
refc.setRadius(10);
cout << refc.getArea() << " " << circle.getArea();
}

- 참조에 의한 호출로 Circle 객체에 참조 전달
#include <iostream>
using namespace std;
class Circle {
private:
int radius;
public:
Circle();
Circle(int r);
~Circle();
double getArea() { return 3.14 * radius * radius; }
int getRadius() { return radius; }
void setRadius(int radius) { this->radius = radius; }
};
Circle::Circle() {
radius = 1;
cout << "생성자 실행 radius = " << radius << endl;
}
Circle::Circle(int radius) {
this->radius = radius;
cout << "생성자 실행 radius = " << radius << endl;
}
Circle::~Circle() {
cout << "소멸자 실행 radius = " << radius << endl;
}
void increaseCircle(Circle& c) {
int r = c.getRadius();
c.setRadius(r + 1);
}
int main() {
Circle waffle(30);
increaseCircle(waffle);
cout << waffle.getRadius() << endl;
}

2. 복사 생성자
1) C++에서 얕은 복사와 깊은 복사
- 얕은 복사(shallow copy)
- 객체 복사 시, 객체의 멤버를 1:1로 복사
- 객체의 멤버 변수에 동적 메모리가 할당된 경우
- 사본은 원본 객체가 할당 받은 메모리를 공유하는 문제 발생
- 깊은 복사(deep copy)
- 객체 복사 시, 객체의 멤버를 1:1로 복사
- 객체의 멤버 변수에 동적메모리가 할당된 경우
- 사본은 원본이 가진 메모리 크기만큼 별도로 동적 할당
- 원본의 동적 메모리에 있는 내용을 사본에 복사
- 완전한 형태의 복사
- 사본과 원본은 메모리를 공유하는 문제 없음

2) 객체 간의 초기화와 대입
- 같은 클래스의 객체 간에 서로 초기화나 대입이 가능
- 객체 간의 초기화 : 복사 생성자 이용
- 같은 클래스의 다른 객체와 같은 값을 갖도록 초기화
- 클래스의 멤버 변수를 1:1로 초기화
- 객체 간의 대입: 대입 연산자 이용
- 같은 클래스의 다른 객체의 값을 대입
- 클래스의 멤버 변수를 1:1로 대입
Circle c1(10);
Circle c2 = c1; // == Circle c2(c1) : 복사생성자를 통한 초기화
Circle c3;
c3 = c1; // 객체 간의 대입, c1 객체를 c3 객체에 비트 단위 복사
3) 복사 생성자(copy constructor)
- 객체의 복사 생성시 호출되는 특별한 생성자
- 같은 클래스의 객체를 이용해서 초기화하는 생성자
- 한 클래스에 오직 1개만 선언 가능
- 클래스에 대한 참조 매개 변수를 가지는 독특한 생성자


Ex) Circle의 복사 생성자와 객체 복사
#include <iostream>
using namespace std;
class Circle {
private:
int radius;
public:
Circle() { radius = 1; }
Circle(int radius) { this ->radius = radius; }
Circle(Circle& c); // 복사 생성자 선언
double getArea() { return 3.14 * radius * radius; }
};
Circle::Circle(Circle& c) { // 복사 생성자 구현
this->radius = c.radius;
cout << "복사 생성자 실행 radius = " << radius << endl;
}
int main() {
Circle src(30); // src 객체의 보통 생성자 호출
Circle dest(src); // dest 객체의 복사 생성자 호출
cout << "원본의 면적 = " << src.getArea() << endl;
cout << "사본의 면적 = " << dest.getArea() << endl;
}

4) 디폴트 복사 생성자
- 클래스에 복사 생성자를 선언하지 않으면, 컴파일러가 자동으로 디폴트 복사 생성자 만들어서 삽입

'프로그래밍 언어 > C++' 카테고리의 다른 글
10) 상속 (0) | 2023.12.09 |
---|---|
9) friend와 연산자 중복 (0) | 2023.12.08 |
7) 여러가지 객체의 생성 방법 (1) | 2023.11.03 |
6) 접근 지정자, static 멤버 (0) | 2023.11.02 |
5) 생성자와 소멸자 (0) | 2023.11.01 |