티스토리 뷰

 C++11 에 등장한 move semantic 에 중요한 함수 두가지가 있다. 바로 std::movestd::forward 함수이다. std::forward std::move 함수를 이해하면 쉽게 이해할 수 있으므로 먼저 std::move 에 대해서 알아보자.

std::move

 함수의 이름만 보면 std::move 가 이동을 수행해줄 것처럼 보이지만 사실 타입 캐스팅이 전부이다. 그런데도 이 함수의 이름이 move 인 이유는 오른값으로 캐스팅을 하기 때문이다. std::move 를 구현하면 다음과 같이 구현할 수 있다.

template<typename T>
decltype(auto) move(T&& param)
{
    using ReturnType = remove_reference_t<T>&&;
    return static_cast<ReturnType>(param);
}

 move 함수가 캐스팅만 해주다보니 std::move 함수를 사용하더라도 이동이 되지 않는 경우가 있다.

class Annotation {
public:
    explicit Annotation(const std::string text)
    : value(std::move(text))
    { ... }
    ...
    
private:
    std::string value;
};

 위의 코드에서 text value 로 이동시키려고 했지만 실제로는 복사가 된다. 그 이유는 const 때문이다.

class string {
public:
    ...
    string(const string& rhs);
    string(string&& rhs);
    ...
};

std::move(text) 의 결과는 const std::string 형식의 오른값이다. 이 값은 이동 생성자에 전달이 불가능하다. 그 이유는 이동 생성자에는 const 타입이 아니기 때문이다. 그러나 복사 생성자에는 전달이 가능하다. const 에 대한 왼값 참조를 const 오른값에 묶는 것이 허용되기 때문이다. 따라서 복사생성자가 호출되게 된다. 여기서 얻게되는 한가지 교훈은 이동을 지원할 객체는 const 로 선언하지 말아야하는 것이다. 우리가 알지 못하게 복사 연산으로 변환될 수 있다.

std::forward

 std::forward std::move 는 거의 같은 역할을 한다. 차이가 있다면 std::forward 는 조건부 캐스팅을 한다는 것이다. 보편 참조를 하는 경우에 이 값이 우측값인지 좌측값인지 우리는 알지 못한다. 코드를 통해 살펴보자.

void process(const Widget& lvalArg);
void process(Widget&& rvalArg);

template<typename T>
void logAndProcess(T&& param) // 보편참조
{
    auto now = std::chrono::system_clock::now();
    
    makeLogEntry("Calling 'process'", now);
    process(std::forward<T>(param));
}

Widget w;

logAndProcess(w);
logAndProcess(std::move(w));

logAndProcess 함수에 전달하는 인자를 좌측값과 우측값으로 보내는 경우로 나누어보았다. param 의 타입 또한 인자가 좌측값이냐 우측값이냐에 따라 좌측값이 될수도 우측값이 될수도 있다. 여기서 좌측값으로 전달되었다고 가정해보자. param 의 타입 또한 좌측값이 될 것이며 const Widget& 을 사용하는 process 함수가 호출 될 것이다. 그런데 만약 std::forward 가 아닌 std:;move를 사용했다면 Widget&& 을 사용하는 process 함수가 호출 될 것이다. 이는 어떤 결과를 만들어낼지 아무도 예측하지 못한다. 이처럼 보편참조를 사용하는 경우에는 std::forward 를 사용해야 안전하다.

 

참고 서적

스콧 마이어스, Effective Modern C++

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함