std::move
와 std::forward
는 C++11에서 도입된 이동 의미론(move semantics)과 완벽한 전달(perfect forwarding)을 위한 핵심 유틸리티 함수들입니다. 두 함수의 차이점과 사용법을 자세히 설명해드리겠습니다.
목적: 객체를 rvalue로 무조건 캐스팅하여 이동 의미론(Move Semantics)을 활성화합니다.
#include <utility>
#include <vector>
#include <string>
std::string str = "Hello World";
std::string moved_str = std::move(str); // str을 rvalue로 캐스팅
// str은 이제 비어있거나 유효하지만 지정되지 않은 상태
std::cout << "Original string: " << moved_str << std::endl; // 이동된 문자열 출력
std::cout << "Moved string: " << str << std::endl; // 원래 문자열은 비어있음
// Original string: Hello World
// Moved string:
목적: 템플릿에서 인수의 원래 value category(lvalue/rvalue)를 유지하면서 전달합니다.
template<typename T>
void wrapper(T&& arg) {
target_function(std::forward<T>(arg)); // arg의 원래 타입 유지
}
// std::move의 간단한 구현
template<typename T>
constexpr std::remove_reference_t<T>&& move(T&& t) noexcept {
return static_cast<std::remove_reference_t<T>&&>(t);
}
// 사용 예시
class MyClass {
std::vector<int> data;
public:
MyClass(std::vector<int> d) : data(std::move(d)) {} // 이동 생성
};
std::vector<int> vec = {1, 2, 3, 4, 5};
MyClass obj(std::move(vec)); // vec의 내용을 obj로 이동
// vec은 이제 빈 상태
// std::forward의 간단한 구현
template<typename T>
constexpr T&& forward(std::remove_reference_t<T>& t) noexcept {
return static_cast<T&&>(t);
}
template<typename T>
constexpr T&& forward(std::remove_reference_t<T>&& t) noexcept {
return static_cast<T&&>(t);
}
// 완벽한 전달 예시
template<typename T>
void make_and_process(T&& arg) {
auto obj = std::make_unique<SomeClass>(std::forward<T>(arg));
// arg가 lvalue면 복사, rvalue면 이동
}
std::move는 "이 객체를 이동하겠다"는 명확한 의도를 표현할 때 사용하며, std::forward는 템플릿에서 매개변수의 원래 특성을 유지하면서 전달할 때 사용합니다.
// std::move 사용 - 명확한 이동 의도
class FileManager {
std::string filename;
std::vector<char> buffer;
public:
void setData(std::vector<char> data) {
buffer = std::move(data); // data를 확실히 이동
}
};
// std::forward 사용 - 완벽한 전달
template<typename... Args>
auto make_shared_custom(Args&&... args) {
return std::make_shared<MyClass>(std::forward<Args>(args)...);
// 각 arg의 원래 lvalue/rvalue 특성 유지
}