프로그래밍 언어/C++

8) 함수와 참조, 복사생성자

busy맨 2023. 12. 8. 21:05

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