본문 바로가기

Information Technology/C++

[C++] std::move(2)

개인의 학습을 목적으로 정리한 글입니다. 이점 참고하고 읽어주세요 ;)


이전 포스팅과 동일한 AutoPtr 헤더파일과 Resource 헤더파일을 가지고 진행합니다.

이번에는 std::move를 사용하는 새로운 예제를 설명해드릴건데요

void print()
	{
		for (unsigned i = 0; i < m_length; ++i)
			std::cout << m_data[i] << " ";
		std::cout << std::endl;
	}

void setAll(const int& v)
	{
		for (unsigned i = 0; i < m_length; ++i)
			m_data[i] = v;
	}

둘 모두 Resource 클래스를 정의한 Resource.h 헤더파일에 구현된 함수들입니다.

단순하게 배열의 값들을 출력하는 print() 함수와,

배열의 값을 입력 값으로 초기화하는 setAll() 함수입니다.

 

{
		AutoPtr<Resource> res1(new Resource(3));
		res1.m_ptr->setAll(3);

		AutoPtr<Resource> res2(new Resource(5));
		res2.m_ptr->setAll(5);

		res1.m_ptr->print();
		res2.m_ptr->print();

		MySwap(res1, res2);

		res1.m_ptr->print();
		res2.m_ptr->print();
}

이 코드는 main함수에 정의한 새로운 예제입니다.

AutoPtr자료형으로 res1과 res2를 각각 다른 배열의 길이를 주면서 초기화시키고

setAll()함수를 통해 res1에는 3, res2에는 5로 채워줍니다.

그 다음에 모두 print()함수로 호출을 해주고 

사전에 정의한 MySwap() 함수로 res1과 res2에 저장된 값을 바꿔줍니다.

 

MySwap()함수의 코드는 다음과 같습니다.

template<class T>
void MySwap(T& a, T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}

위에 있는 main 함수를 실행하게 되면

위와 같이 생성자, 소멸자, 복사 생성자, 대입 연산자가 복잡하게 출력됩니다.

이 결과를 통해서는

'L-value'를 사용하는 복사 생성자와 대입 연산자의 경우 Swap 알고리즘에도 꽤 많은 과정이 수반된다..!'정도만 느끼시면 될 것 같습니다.

그럼 이제 'R-value'를 사용하면 어떤 결과가 나오는지 봐야겠죠?

R-value를 사용하는 move-sementics 방법으로 Swap 알고리즘을 사용하려면

template<class T>
void MySwap(T& a, T& b)
{
	T tmp{ std::move(a) };
	a = std::move(b);
	b = std::move(tmp);
}

위의 코드블록과 같이 std::move()를 사용하면 됩니다.

나머지 코드는 건드리지 않고 다시한번 main 함수를 실행하게 되면

Swap 과정에서 복사 생성자를 생성하지 않고 한결 간소화?되어 출력된 결과를 확인할 수 있습니다.

 

혹시 몰라 말씀드리는데,

std::move()는 사용하려는 클래스에서 사전에 move-sementics의, 그러니까 R-value를 사용하는 복사 생성자, 대입 연산자가 존재할 때에만 사용할 수 있습니다.

※ vector처럼 자주 사용하는 stl에는 자동으로 std::move()를 사용할 수 있게 기능이 구현되어 있다고 하는데, 이건 필요할 때 직접 찾아보면 될 것 같습니다!