해당 글은 함수와 참조에 대한 이해를 바탕으로 작성하였습니다.
함수와 참조에 대한 내용을 원하신다면 아래의 링크를 클릭해주세요!
[C++] 05-1. 함수와 참조
복사 : 원본과 동일한 별개의 사본을 만드는 것
classs Person {
int id;
char *name;
......
}
얕은 복사
: 원본 객체의 멤버가 그대로 사본 객체에 복사되므로, 사본은 원본의 name 메모리를 공유깊은 복사
: name 포인터가 가리키는 메모리까지 복사하여 원본과 사본의 name은 별개의 메모리를 가리키므로, 완전한 복사가 이루어짐아래 코드 : Circle 클래스의 복사 생성자와 객체 복사
#include <iostream>
using namespace std;
class Circle {
private:
int radius;
public:
Circle(const Circle& c); // 복사 생성자 선언
Circle() { radius = 1; }
Circle(int radius) { this->radius = radius; }
double getArea() { return 3.14*radius*radius; }
};
Circle::Circle(const 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;
}
복사 생성
: 객체가 생성될 때 원본 객체를 복사하여 생성복사 생성자
(copy construct) : 자신과 같은 클래스 타입의 다른 객체에 대한 참조를 인수로 전달받아, 그 참조를 가지고 자신을 초기화하는 방법Circle src(30);
Circle dest(src);
Circle::Circle(const Circle& c) { // 복사 생성자 구현
this->radius = c.radius;
cout << "복사 생성자 실행 radius = " << radius << endl;
}
디폴트 복사 생성자
class Book {
double price;
int pages;
char* title;
char* author;
public:
Book(double pr, int pa, char* tm char* a);
~Book();
};
복사 생성자가 없는 위의 Book클래스의 경우 컴파일러가 아래 형식의 디폴트 복사 생성자를 삽입함
Book(const Book& book) {
this->price = book.price;
this->pages = book.pages;
this->title = book.title;
this->author = book.author;
}
✅ 원본과 사본 각 객체가 소멸될 때, 같은 메모리 공간을 공유하기 때문에 한 객체가 이미 반환한 메모리를 다시 반환하게 됨
⇒ 실행 시간 오류 발생 + 프로그램 비정상 종료
#define _CRT_SECURE_NO_WARNINGS //비주얼 스튜디오에서 strcpy로 인한 오류를 막기 위한 선언문
#include <iostream>
#include <cstring>
using namespace std;
class Person { // Person 클래스 선언
char* name;
int id;
public:
Person(int id, const char* name); // 생성자
Person(const Person& person); // 복사 생성자
~Person(); // 소멸자
void changeName(const char *name);
void show() { cout << id << ',' << name << endl; }
};
Person::Person(int id,const char* name) { // 생성자
this->id = id;
int len = strlen(name); // name의 문자 개수
this->name = new char [len+1]; // name 문자열 공간 핟당
strcpy(this->name, name); // name에 문자열 복사
}
Person::Person(const Person& person) { // 복사 생성자
this->id = person.id; // id 값 복사
int len = strlen(person.name);// name의 문자 개수
this->name = new char [len+1]; // name을 위한 공간 핟당
strcpy(this->name, person.name); // name의 문자열 복사
cout << "복사 생성자 실행. 원본 객체의 이름 " << this->name << endl;
}
Person::~Person() {// 소멸자
if(name) // 만일 name에 동적 할당된 배열이 있으면
delete [] name; // 동적 할당 메모리 소멸
}
void Person::changeName(const char* name) { // 이름 변경
if(strlen(name) > strlen(this->name))
return; // 현재 name에 할당된 메모리보다 긴 이름으로 바꿀 수 없다.
strcpy(this->name, name);
}
int main() {
Person father(1, "Kitae"); // (1) father 객체 생성
Person daughter(father); // (2) daughter 객체 복사 생성. 복사 생성자 호출
cout << "daughter 객체 생성 직후 ----" << endl;
father.show(); // (3) father 객체 출력
daughter.show(); // (3) daughter 객체 출력
daughter.changeName("Grace"); // (4) // daughter의 이름을 "Grace"로 변경
cout << "daughter 이름을 Grace로 변경한 후 ----" << endl;
father.show(); // (5) father 객체 출력
daughter.show(); // (5) daughter 객체 출력
return 0; // (6), (7) daughter, father 객체 소멸
}
daughter의 name에 메모리가 따로 동적 할당되고, father의 name 문자열이 복사되어 같은 문자열 "Kitea"로 초기화
daughter 객체의 name을 "Grace"로 변경해도, father의 name은 "Kitea"로 그대로 남아 있음
✅ 원본 객체에 동적 할당된 메모리 크기 내에서만 변경 가능
main() 함수의 return 0;문이 실행되면 daughter 객체가 먼저 소멸되고 daughter의 name에 할당된 메모리를 힙에 반환
-> daughter의 소멸 뒤 father 객체가 소멸되면서 자신의 name에 할당된 메모리를 힙에 반환하게 됨
=> 얕은 복사 생성자에서 일어난 중복 반환은 발생하지 않음
: 복사 생성자를 구현해 놓지 않은 상태에서 컴파일러가 복사 생성자를 자동으로 호출하는 경우
(1) 객체로 초기화하여 객체가 생성될 때
Person son = father; // 복사 생성자 자동 호출
Person son(father);
Person son;
son = father;
(2) '값에 의한 호출'로 객체가 전달될 때
void f(Person person) { // 매개 변수 person이 생성될 때 복사 생성자 호출
......
}
Person father(1, "Kitae");
f(father); // 값에 의한 호출로 father 객체 전달
Person person(father);
(3) 함수가 객체를 리턴할 때
return 문은 리턴 객체의 복사본을 생성하여 호출한 곳으로 전달하는데 이때 복사생성자 호출됨
Person g(){
Person mother(2, "Jane");
return mother; // mother의 복사본을 생성하여 복사본 리턴, 사본이 만들어질 때 복사 생성자 호출
};
g();
해당 포스팅은 '황기태, 『명품 C++ Programming』, 생능출판사'를 참고하여 작성하였습니다.