[C++기초] 16. 이동 생성자 및 이동 대입 연산자
INDEX
rvalue와 복사생성자
값의 분류
- lvaue
- rvalue
lvalue란?
- 단일 식을 넘어 지속되는 개체
- 주소가 있음
- 이름이 있는 변수
- const변수
- 배열 변수
- 비트 필드
- 공용 구조체
- 클래스 멤버
- 좌측 값 참조(&)로 반환하는 함수 호출
- 문자열 리터럴
- 결국 지금까지 봐 온 많은 것들
rvalue란?
-
lvalue가 아닌 개체
-
사용되는 단일 식을 넘어 지속되지 않는 일시적인 값
-
주소가 없는 개체
-
리터럴
-
참조로 반환되지 않는 함수 호출
-
i++, i–같은 것들
-
기본적으로 지원되는 산술식, 논리식, 그리고 비교식
-
열거형
-
람다
-
과거 C++ 의 문제(C++11 이전)
- 함수 호출 시 임시 개체(rvalue)에 대한 복사가 너무 많이 일어남
복사를 어떻게 막을까?
- rvalue 참조와 이동 문법으로 해결할 수 있다.
rvalue 참조 (&&)
- C++ 11 이후에 새로 나온 연산자
- 기능상 & 연산자와 비슷
- & 연산자는 lvalue 참조에 사용
- && 연산자는 rvalue 참조에 사용
rvalue 참조, stdmove(), 이동생성자
예시 : rvalue참조
float CalculateAverage() { float average; // ... return average; } int main() { int number = 10; int&& rNumber = number; // 에러, number는 lvaule int&& rNumber1 = 10; // OK, 10은 rvalue float&& rAverage = CalculateAverage(); // OK, CaculateAverage()는 rvalue }
std::move()
- rvalue 참조를 반환
- lvalue를 rvalue로 변환
이동생성자
`
:: ( &&) `
-
다른 개체 맴버 변수들의 소유권을 가져옴
-
복사 생성자와 달리, 메모리 재할당을 하지 않음
-
복사 생성자보다 빠름
-
약간 얕은 복사와 비슷
MyString::MyString(MyString&& other) { // ... }
예시 : MyString 이동 생성자
MyString.h
class MyString { public: MyString(MyString&& other); // 이동 생성자 MyString(const MyString& other); // 복사 생성자 MyString(const char* str); // ... private: char* mString; int mSize; };
MyString.cpp
// 이동 생성자 MyString::MyString(MyString&& other) : mString(other.mString) , mSize(other.mSize) { other.mString = nullptr; other.mSize = 0; } // 복사 생성자 MyString::MyString(const MyString& other) : mSize(other.mSize) { mString = new char[mSize]; memcpy(mString, other.mString, mSzie); } MyString::MyString(const char* str) : mSize(strlen(str) +1) { mString = new char[mSize]; memcpy(mString, str, mSize); }
Main.cpp
MyString studentName("Lulu"); MyString copiedName(studentName); MyString copiedName2(std::move(studentName));
- 이동 생성자를 사용함으로써 메모리 재할당을 막음
이동 대입 연산자
이동 대입 연산자
<class_name>& <class_name>::operator=(<class_name>&&)
-
이동 생성자와 같은 개념
-
다른 개체 맴버 변수들의 소유권을 가져옴
-
메모리 재할다응ㄹ 하지 않음
-
얕은 복사
MyString& MyString::Operator=(MyString&& other) { // ... }
예시 : 이동 대입 연산자
MyString.h
class MyString { public: MyString& operator=(MyString&& other); // ... private: char* mString; int mSize; };
MyStirng.cpp
MyString& MyString::operator=(MyString&& other) { if(this != &other) { delete[] mString; mString = other.mString; mSize = other.mSize; other.mString = nullptr; other.mSize = 0; } return *this; }
Main.cpp
MsString studnetName("Lulu"); MyString anotherStudentName("Teemo"); anotherStudentName = std::move(studnetName);
STL 컨테이너용 이동 문법
- C++ 11 이후로, STL 컨테이너에 이동 생성자와 이동 대입이 생김
- 그래서, 이것들을 따로 구현할 필요가 없음
rvalue 최적화
- 또다른 C++ 프로그래밍 유행어
- 이동 생성자와 이동 대입 연산자
- 아직 유효
- 포인터 대신 개체 자체를 반환하는 함수
- 함수에서 rvalue를 반환하는 것은 실제로 매우 느림
- 반환 값 최적화라고 하는 컴파일러 최적화를 깨뜨림
베스트 프랙티스
- 기본적으로 그냥 개체를 반환
- 더 빨라진다고 입증된 경우에만 함수가 rvalue를 반환하도록 바꾸자