오븐 노트

[C++] 오른값 참조 (rvalue reference) 본문

Develop/C++

[C++] 오른값 참조 (rvalue reference)

오 븐 2023. 12. 30. 21:25
#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include <algorithm>

class Pet
{

};

class Knight
{
public:
	Knight()
	{
		cout << "Knight()" << endl;
	}

	// 복사 생성자
	Knight(const Knight& knight)
	{
		cout << "const Knight&" << endl;
	}

	// 이동 생성자
	Knight(Knight&& knight)
	{

	}

	~Knight()
	{
		if (_pet)
			delete _pet;
	}

	// 복사 대입 연산자
	void operator=(const Knight& knight) // 데이터를 사용해도 되지만 원본 데이터를 건드릴 권한은 주지않음.
	{
		cout << "operator=(const Knight&)" << endl;

		// 깊은 복사
		_hp = knight._hp;

		if (knight._pet)
			_pet = new Pet(*knight._pet); // 참고할 정보만 꺼내와서 버전을 나누고 원본은 유지
	}

	// 이동 대입 연산자
	void operator=(Knight&& knight) noexcept // 경고를 뱉지 않는다
	{
		cout << "operator=(Knight&& knight)" << endl;
		
		// 얕은 복사
		_hp = knight._hp;
		_pet = knight._pet;

		knight._pet = nullptr;
	}

	void PrintInfo() const
	{

	}

public:
	int _hp = 100;
	Pet* _pet = nullptr;
};

void TestKnight_Copy(Knight knight) { }
void TestKnight_LValueRef(Knight& knight) { }
void TestKnight_ConstLValueRef(const Knight& knight) { knight.PrintInfo(); } // const가 붙은 함수들만 호출 할 수 있게되는 불편함이 있음
void TestKnight_RValueRef(Knight&& knight) { } // 이동 대상 (이 함수가 호출 된 후 더 이상 활용하지않을것이니 멋대로해도된다 / 원본 데이터 유지할 필요 없다)

int main()
{
	// 왼값(lvalue) vs 오른값(rvalue)
	// - lvalue : 단일식을 넘어서 계속 지속되는 개체
	// - rvalue : lvalue가 아닌 나머지 (임시 값, 열거형, 람다, i++ 등)

	//int a = 3;

	Knight k1;

	TestKnight_Copy(k1);

	TestKnight_LValueRef(k1);
	//TestKnight_LValueRef(Knight());

	TestKnight_ConstLValueRef(Knight());

	TestKnight_RValueRef(Knight());

	TestKnight_RValueRef(static_cast<Knight&&>(k1));

	Knight k2;
	k2._pet = new Pet();
	k2._hp = 1000;

	// 원본은 날려도 된다 << 는 Hint를 주는 쪽에 가깝다
	Knight k3;
	//k3 = static_cast<Knight&&>(k2); // 복사하는 개념이 아니라 이동하는 개념

	k3 = std::move(k2); // 윗줄과 사실상 같은 역할 // 오른값 참조로 캐스팅
	// std::move의 본래 이름 후보 중 하나가 rvalue_cast
	// 이런 개념으로 인해 c++11 이전과 비교하여 속도가 많이 빨라졌다

	std::unique_ptr<Knight> uptr = std::make_unique<Knight>(); // 단 하나만 존재해야하는 포인터 (스마트 포인터)
	std::unique_ptr<Knight> uptr2 = std::move(uptr); // 오른값 참조로 캐스팅 해주었기에 소유권 자체가 uptr2로 이양된다

	return 0;
}

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 - 인프런 | 강의
 
C++ 카테고리의 글은 인프런 Rookiss님의 강의를 공부하며 정리하는 내용입니다.
이미 알고 있는 내용도 다시 정리 되어있을 수 있습니다.

 

모든 글은 제가 공부하기 위해 작성합니다.

'Develop > C++' 카테고리의 다른 글

[C++] 람다 (lambda)  (0) 2024.01.02
[C++] 전달 참조 (forwarding reference)  (0) 2024.01.02
[C++] override, final  (0) 2023.12.28
[C++] delete(삭제된 함수)  (0) 2023.12.13
[C++] enum class  (0) 2023.12.13