[大杯C++15意味移動とスマートポインタ

17457 ワード

Created: June 6, 2021 11:26 AM
Tag: move semantics, r-value references, smart pointers

15.1移動語義とスマートポインタ移動語義、スマートポインタ

// Resource.h
#include <iostream>

class Resource
{
public:
	int m_data[100];

public:
	Resource()
	{
		std::cout << "Resource constructed" << std::endl;
	}

	~Resource()
	{
		std::cout << "Resource destroyed" << std::endl;
	}
};

// ==============================
// AutoPtr.h
#include <iostream>

template<class T>
class AutoPtr
{
public:
	T *m_ptr = nullptr;

public:
	AutoPtr(T *ptr = nullptr)
		: m_ptr(ptr)
	{
	}

	~AutoPtr()
	{
		if (m_ptr != nullptr) delete m_ptr;
	}

	// 소유권 이동 구현
	AutoPtr(AutoPtr & a)
	{
		m_ptr = a.m_ptr;
		a.m_ptr = nullptr; // 첫번째 포인터를 null로 바꿔버린다
	}

	AutoPtr &operator = (AutoPtr &a)
	{
		if (&a == this)
			return (*this);

		delete m_ptr;
		m_ptr = a.m_ptr;
		a.m_ptr = nullptr;
		return (*this);
	}

	T &operator*() const { return (*m_ptr); }
	T *operator->() const { return (m_ptr); }
	bool isNull() const { return (m_ptr == nullptr); }
}

// ==============================
// main.cpp
#include <iostream>
#include "Resource.h"
#include "AutoPtr.h"

using namespace std;

// RAII: resource acquisition is initialization 
// 동적할당을 한 부분에서 그것이 해제되어야 한다는 개념

void doSomething()
{

	// Resource *res = new Resource; // dull pointer
	AutoPtr<Resource> res(new Resource); // smart pointer

	// delete res; // <- smart pointer를 사용하기 때문에 필요없음

	return ;
}

int main(void)
{
	doSomething();

	// Auto Pointer의 한계
	{
		AutoPtr<Resource> res1(new Resource);
		AutoPtr<Resource> res2;

		cout << std::boolalpha;

		cout << res1.m_ptr << endl;
		cout << res2.m_ptr << endl; // null

		res2 = res1; // <- 문제발생: 소유권의 move가 필요하다! // move semantics

		cout << res1.m_ptr << endl;
		cout << res2.m_ptr << endl; // 이미 지워진 메모리를 또 지우려고 시도하게 되면 runtime error 발생
	}

	// syntax vs semantics
	// compile vs 실제 내부적 의미

	// value semantics(copy semantics)
	// reference semantics(pointer)
	// move semantics

	return (0);
}
💡 syntax vs semantics=compile vs実際の内部意味
1) value semantics (copy semantics)
2) reference semantics (pointer)
3) move semantics

15.2右値参照R-valueReference

#include <iostream>
using namespace std;

void doSomething(int &lref)
{
	cout << "l-value ref" << endl;
}

void doSomthing(int &&ref)
{
	cout << "r-value ref" << endl;
}

// ...

int main(void)
{
	int x = 5;
	const int cx = 6;

	// L-value references

	int &lr1 = x;		// modifiable l-values
	//int &lr2 = cs;	// non modifiable l-values // 주석은 문법상 컴파일이 안되는 코드임
	//int &lr3 = 5;		// r-values // r-values에 대한 reference는 가질 수 없다

	const int &lr4 = x; // modifiable l-values
	const int &lr5 = cx; // non-modifiable l-values
	const int &lr6 = 5; // r-values

	// r-value references

	//int &&rr1 = x;	// modifiable l-values
	//int &&rr2 = cx;	// non-modifiable l-values
	int &&rr3 = 5;		// r-values

	//const int &&rr4 = x;	// modifiable l-values
	//const int &&rr5 = cx; // non modifiable l-values
	const int &&rr6 = 5;	// r-values

	// L/R-value reference parameters
	doSomething(x); // l-value
	doSomething(5); // non l-value == r-value

	return (0);
}