-
C++ Study. move assignment operatorc++ 2024. 1. 21. 16:52
move semantics
- 기존의 복사 대입 연산자(copy assignment operator)와는 다르게 이동 대입 연산자(move assignment operator)를 이용하여 객체 소유권을 이전하여 메모리를 효율적으로 이동시키는 것
move semantics을 하기 위해 필요한 것들
- std::move() 함수
- 복사 대입 연산자가 아닌 이동 대입 연산자를 호출하기 위해 사용
- 단순히, 전달받은 인자를 rvalue reference(참조자)로 캐스팅해서 리턴
- rvalue reference로 캐스팅하려면 → 타입&&
static_cast<Object&&>(obj) == std::move(obj1) // 양쪽이 같은 작업 수행
- move assignment operator(이동 대입 연산자)
- 우항에 rvalue 참조자가 있고, = 연산이 수행되어야 할 때 호출되는 연산자
- 클래스 만들 때 이걸 정의해줘야 이동 연산이 된다. 없으면 복사 대입 연산자가 수행됨.
- 클래스에서 연산자 오버라이딩하듯이 정의내리면 된다.
예시 코드
#include <iostream> class MyString { private: char* data; public: // 생성자, 소멸자, 복사 생성자 등 생략 // 이동 대입 연산자 정의 MyString& operator=(MyString&& other) noexcept { if (this != &other) { delete[] data; // 기존 데이터 삭제 data = other.data; // other의 데이터를 기존 data로 이동(data 포인터가 가리키는 주소 변경) other.data = nullptr; // other의 데이터는 nullptr을 가리키도록 함 } return *this; // 해당 객체의 lvalue 반환 } }; int main() { MyString str1("Hello"); MyString str2("World"); // 이동 함수(move) 호출 -> 내부적으로 이동 대입 연산자가 호출됨 str1 = std::move(str2); return 0;
&&에 대한 설명
- rvalue 참조를 한다.
- &&와 &의 다른점?
- 예시코드
int a = 10; int &b = a; // OK. a는 lvalue. int &&c = a; // Compile Error: a는 lvalue인데 &&는 rvalue 참조 int &&c = 10; // OK, 10은 리터럴로 rvalue
- b는 lvalue 참조자이다. lvalue는 객체를 수정하거나 다른 함수로 전달할 때 유용
- c는 rvalue 참조자이다. 오른쪽 값(임시 객체, 리터럴 등)을 참조하기 위해 사용.
- &는 lvalue 참조이다.
- 왜 rvalue 참조가 필요한지?
- -> rvalue 참조는 주로 move semantic에서 활용된다. move는 복사가 아니라 rvalue값 자체가 이동되어야 하고, 임시 객체나 rvalue는 그 자체로 이동이 가능한 값이기 때문에 rvalue 참조를 통해 rvalue에 접근해서 이동 연산을 수행한다.
- lvalue 참조(&)로 move assignment operator 구현하면 어떻게 되나?
MyClass& operator=(const MyClass& other) { // data = &other->data; // other->data = null; // error // 잘못된 방식: Lvalue 참조를 사용하여 복사 연산을 수행 // 이 경우 이동 의미론의 이점을 활용할 수 없음 // 새로운 객체에 복사를 수행하는 것으로, 이는 기존 복사 대입 연산자와 다르지 않음 // 실제로 소유권의 이동이 아닌, 단순한 복사가 이루어짐 // ... return *this; }
- 임시 객체란(Temporary Object)?
- -> 임시객체란 표현식이 평가되면서 생성되고, 해당 표현식이 종료되면 자동으로 소멸되는 임시적인 객체를 말한다. 함수 호출, 연산 등에서 자주 발생한다.
// 1. 함수 호출시 int add(int a, int b) { return a + b; } int result = add(3, 4); // 임시 객체가 반환됨, int는 이동 대입 연산자 없어서 복사 일어남 // 2. 연산 string fullName = "John" + " " + "Doe"; // 문자열 연결 시 임시 객체 생성, 이동 일어남 // 3. 형변환 double value = 3.14; int intValue = static_cast<int>(value); // static_cast 시에 임시 객체 생성됨 // 4. 임시 객체를 반환하는 함수 string getName() { return "Alice"; // 임시 객체 반환 } int temp(){ string name = getName(); // getName()의 반환값이 임시객체, // 반환값은 문자열 리터럴이라 lvalue지만 임시객체이기 때문에 move semantic이 일어남. }
참고
'c++' 카테고리의 다른 글
C++ Study. module system (0) 2024.01.21 C++ Study. stl unordered_set (0) 2024.01.21 C++ Study. final, override (1) 2024.01.21 C++ 스터디. standard template library (1) 2024.01.21 C++ Primer CH15. Object-Oriented Programming (0) 2024.01.21