본문 바로가기
공부

[C++] 특수 멤버 함수 (Special Member Function)

by MY블로그 2023. 5. 14.

특수 멤버 함수는 6가지로 구성이 되어 있다.

  1. 기본 생성자 : Constructor (C)
  2. 복사 생성자 : Copy Constructor (CC)
  3. 복사 대입 연산자 : Copy Assignment Operator (CAO)
  4. 이동 생성자 : Move Constructor (MC)
  5. 이동 대입 연산자 : Move Assignment Operator (MAO)
  6. 소멸자 : Destructor (D)

전체코드 (접은글 더보기 참조)

더보기
#include<iostream>
using namespace std;

class Test
{
public:
	int* ptr;
	int value;

public:
	Test(int* ptr, int value){
		cout << "생성자" << endl;

		this->ptr = nullptr;

		if (ptr != nullptr)
			this->ptr = new int(*ptr);

		this->value = value;
	}

	~Test(){
		cout << "소멸자" << endl;

		if (ptr != nullptr){
			delete ptr;
			ptr = nullptr;
		}
	}

	Test(const Test& other){
		cout << "복사 생성자" << endl;

		this->ptr = nullptr;

		if (other.ptr != nullptr)
			this->ptr = new int(*other.ptr);

		this->value = other.value;
	}

	Test& operator=(const Test& other)
	{
		cout << "복사 대입 연산자" << endl;

		if (this == &other)
			return *this;

		if (this->ptr != nullptr){
			delete this->ptr;
			this->ptr = nullptr;
		}

		if (other.ptr != nullptr){
			this->ptr = new int(*other.ptr);
		}
		else 
			this->ptr = nullptr;

		return *this;
	}

	Test(Test&& other){
		cout << "이동 생성자" << endl;

		this->ptr = move(other.ptr);
		this->value = move(other.value);

		other.ptr = nullptr;
	}

	Test& operator= (Test&& other){
		cout << "이동 대입 연산자" << endl;

		if (this  == &other)
			return *this;

		if (this->ptr != nullptr){
			if (this->ptr != nullptr && this->ptr != other.ptr){
				delete this->ptr;
				this->ptr = nullptr;
				this->ptr = move(other.ptr);
			}
		}
		
		else 
			this->ptr = move(other.ptr);

		this->value = other.value;

		other.ptr = nullptr;

		return *this;
	}
};

 

1. 기본 생성자 : Constructor (C)
	Test(int* ptr, int value)
    {
		cout << "생성자" << endl;

		this->ptr = nullptr; // 우선 this->ptr 를 비워준다.

		if (ptr != nullptr) // 매개변수로 들어온 ptr이 값이 있다면(nullptr이 아니라면)
			this->ptr = new int(*ptr); // this->ptr 에 매개변수 ptr 값 동적할당

		this->value = value; // this->value 에 매개변수 value 값 복사대입
	}
2. 복사 생성자 : Copy Constructor (CC)
	Test(const Test& other) 
    {
		cout << "복사 생성자" << endl;

		this->ptr = nullptr; // this->ptr 을 비워주고

		if (other.ptr != nullptr) // 매개변수ptr이 nullptr이아니라면(값이있다면)
			this->ptr = new int(*other.ptr); // 동적할당

		this->value = other.value; // this->value 에 매개변수 other.value 복사대입
	}
3. 복사 대입 연산자 : Copy Assignment Operator (CAO)
	Test& operator=(const Test& other) // operator= 사용
	{
		cout << "복사 대입 연산자" << endl;

		if (this == &other) // 본인과 매개변수other이 같다면 *this 본인반환
			return *this;

		if (this->ptr != nullptr) // this->ptr이 비어있지 않다면 (뭔가값이있다는것!)
        {
			delete this->ptr; // this->ptr을 삭제하고
			this->ptr = nullptr; // this->ptr 을 비워준다.
		}

		if (other.ptr != nullptr) // 들어온 매개변수가 nullptr이아니라면(값이있다면)
        {
			this->ptr = new int(*other.ptr); // this->ptr에 동적할당
		}
		else // 위의 조건에 일치하지않을때 this->ptr은 비어있는 것으로 한다.
			this->ptr = nullptr;

		return *this; // *this 반환
	}
4. 이동 생성자 : Move Constructor (MC)
	Test(Test&& other) // && 사용
    {
		cout << "이동 생성자" << endl;

		this->ptr = move(other.ptr); // move 함수는 Lvalue>Rvalue/Rvalue>Lvalue 바꿔주는 함수이다.
		this->value = move(other.value);

		other.ptr = nullptr; // 주소이동이 끝난 매개변수쪽은 nullptr로 초기화해준다.
	}
5. 이동 대입 연산자 : Move Assignment Operator (MAO)
	Test& operator= (Test&& other) // operator= 사용 && 사용
    {
		cout << "이동 대입 연산자" << endl;

		if (this == &other) // this와 매개변수가 같다면
			return *this; // 그대로 반환

		if (this->ptr != nullptr) // this가비어있지않을때
        {
			if (this->ptr != nullptr && this->ptr != other.ptr) // this가 비어있지않고 매개변수랑 값이다를때
            {
				delete this->ptr; // this 쪽을 제거하고
				this->ptr = nullptr; // nullptr 로 초기화해준다.
				this->ptr = move(other.ptr); // 그후에 매개변수의 것을 이동시켜준다.
			}
		}

		else // this가 매개변수와 같지않고 비어있을때
			this->ptr = move(other.ptr); // 그냥 그대로 옮긴다.

		this->value = other.value; // this->value 도 매개변수value로 대입해준다.

		other.ptr = nullptr; // 모든작업이 끝난뒤 매개변수쪽 ptr을 nullptr로 초기화 해준다.

		return *this; // 마지막으로 반환 시켜준다.
	}
6. 소멸자 : Destructor (D)
	~Test() 
    {
		cout << "소멸자" << endl;

		if (ptr != nullptr) // ptr에 값이 있다면
        {
			delete ptr; // ptr 지워주고
			ptr = nullptr; // 초기화
		}
	}

 

댓글