l-value는 어떠한 메모리 위치를 가리키는데, & 연산자를 통해 그 위치를 참조할 수 있다.
r-value는 l-value가 아닌 값들, 대입 시 오른쪽에만 올 수 있는 value들이다. (임시 객체, 함수가 반환하는 객체, move()가 반환하는 값 등)
표현식 이후에 사라지면 r-value 사라지지 않으면 l-value
l-value reference 는 &하나로 정의
1. void foo(X&); 만 구현했을 경우
ㄴ foo는 좌측값만 인자로 받을 수 있다.
2. void foo(X const&);만 구현했을 경우
ㄴ foo는 좌측 값과 우측 값을 인자로 받을 수는 있지만 우측값일 때를 구별할 수가 없음
3.void foo(X &) or void foo(X const &); 와
void foo(X &&); (우측 값만 받음) 모두 구현해야 구분할 수 있다.
우측값 참조라 선언되었더라도 이름이 있다면 좌측값 없다면 우측값이다.
예시 1.
void foo(X&& x) {
X anotherX = x; // x가 우측값 레퍼런스로 정의되었고 이름이 있기 때문에 좌측값이다. X(X const & rhs) 가 호출됨
}
예시 2.
X&& goo();
X x = goo(); // 이름이 없으므로 우측값. 즉 X(X&& rhs) 가 호출됨
std::move()
ㄴ 레퍼런스를 인자로 받고, 이것을 우측값 참조로 리턴하는 함수 (이름을 없애는 함수? 우측 값으로 바꿔주는 함수? 임시 객체를 리턴하는 함수?)
이동 생성자
MyString::MyString(MyString &&str) {
std::cout << "이동 생성자 호출 !" << std::endl;
string_length = str.string_length;
string_content = str.string_content;
memory_capacity = str.memory_capacity;
// 임시 객체 소멸 시에 메모리를 해제하지
// 못하게 한다.
str.string_content = nullptr;
}
MyString::~MyString() {
// 임시 객체의 string_content가 nullptr(0)이면 string_content를 해제하지 않는다.
if (string_content) delete[] string_content;
}
MyString str3 = str1 + str2; // operator+함수로 리턴된 임시 객체는 우측 값이다.
객체를 STL 컨테이너에 넣을 때, 이동 생성자 작성 시 주의할 점
STL 컨테이너들은 이동 생성자에서 예외가 발생했을 때 처리할 수 없기 때문에 이동 생성자를 noexcept로 명시하지 않으면 이동 생성자 대신 복사 생성자를 사용한다.
참조:
'C++' 카테고리의 다른 글
C++ 가상 함수, virtual 소멸자, 가상 함수 테이블, 추상 클래스 (0) | 2022.08.25 |
---|---|
C++ 템플릿, 함수 객체(Functor) (0) | 2022.08.25 |
C++ 문자열 처리 (0) | 2022.08.24 |
C++ memory order, atomic객체 (0) | 2022.08.24 |
C++ thread, mutex, condition_variable (0) | 2022.08.23 |