우리는 이름이 없는 객체를 할당하고 사용할 수 있다. (eg. new를 사용하여 생성) 이상하게 보이는 표현식에 할당하는 것도 가능하다. <메모리 속의 어떤 것>. 이것은 대상에 대한 가장 단순하고 기본적인 개념이다. 즉, 객체는 연속적인 저장 영역이다. lvalue는 객체를 참조하는 표현식이다. "lvalue"라는 단어는 원래 '할당의 왼쪽에 있을 수 있는 것'을 의미하기 위해 만들어졌다. 그러나 모든 lvalue가 할당의 왼쪽에 사용될 수 있는 것은 아니다.
lvalue 유형과 선언은 상수를 참조할 수 있다. const로 선언되지 않은 lvalue는 종종 수정 가능한 lvalue라고 한다. 객체에 대한 단순하고 낮은 수준의 이 개념은 클래스 객체 및 다형성 유형의 객체 개념과 혼동되어서는 안 된다.
Lvalues and Rvalues
lvalue의 개념을 보완하기 위해 rvalue의 개념이 있다. 대략적으로 rvalue의 임시 값(eg. 함수에서의 반환 값)과 같이 'lvalue가 아닌 값'을 의미한다. 좀 더 기술적인 것이 필요하다면 lvalue 및 rvalue에 대한 보기가 필요하다. 주소 지정, 복사 및 이동과 관련하여 객체에 중요한 두 가지 속성이 있다.
- Has identity : 프로그램은 객체의 이름, 포인터 또는 참조를 가지고 있으므로 두 객체가 동일한지 여부, 객체의 값이 변경되었는지 등을 판별할 수 있다.
- Movable : 객체가 다음 위치에서 이동할 수 있다. ( 즉, 해당 값을 다른 위치로 이동할 수 있다 ) 위치를 지정하고 객체를 복사하는 대신 유효하지만 지정되지 않은 상태로 두자.
C++ 언어 규칙을 정확하게 설명하려면 두 속성의 4가지 가능한 조합 중 3가지가 필요하다. "이동 가능한 m"과 "식별 가능한 i"를 사용하여 이 표현 분류를 그림으로 나타낼 수 있다.
따라서 lvalue는 식별 가능하고 이동할 수 없다. (이동 후 검사할 수 있기 때문) rvalue는 이동할 수 있는 모든 것이다. 그리고 prvalue(pure rvalue), glvalue(generalized lvalue), 그리고 xvalue(extraordinary or expert vlaue)가 있다.
예를 들자면,
void f(vector<string>& vs)
{
vector<string>& v2 = std::move(vs); // move vs to v2
// ...
}
여기서 std::move(vs)는 xvalue다. 분명히 식별자를 가지지만 (vs 로만 참조 가능) std::move()를 호출하여 명시적으로 이동 권한을 부여하고 있다. 실용적인 프로그래밍의 경우 일반적으로 rvalue 및 lvalue 측면에서 생각하면 충분하다. 모든 표현식은 lvalue 또는 rvalue지만 둘 다인 것은 아니다.
객체의 수명
객체의 수명은 생성자에서 시작되고 소멸자에서 종료된다. int와 같이 선언된 생성자가 없는 형식의 객체는 아무 작업도 수행하지 않은 기본 생성자와 소멸자가 있는 것으로 간주할 수 있다.
수명을 기준으로 객체를 분류하면 다음과 같다.
- Automatic : 프로그래머가 달리 지정하지 않는 한, 함수에서 선언된 객체는 정의가 발견될 때 생성되고 범위를 벗어날 때 소멸된다. 이러한 객체를 자동 객체라고 한다. 일반적인 구현에서 자동 객체는 Stack에 할당된다. 함수의 각 호출은 자동 객체를 보유하기 위해 자체 Stack frame을 가져온다.
- Static : 전역 또는 네임스페이스 범위에서 선언된 객체와 함수 또는 클래스에서 선언된 Static은 한 번만 생성되고 초기화되고 프로그램이 종료될 때까지 살아 있는다. 이런 객체를 정적 객체라고 한다. 정적 객체는 프로그램 실행 수명 동안 동일한 주소를 갖는다. 정적 객체는 모든 thread에서 공유되기 때문에 다중 thread 프로그램에서 심각한 문제를 일으킬 수 있다. 일반적으로 데이터 경쟁을 피하기 위해 locking이 필요하다.
- Free store : new 및 delete 연산자를 사용하여 수명이 다음과 같은 객체를 생성할 수 있다.
- Temporary objects (eg. 계산 중간 결과 또는 const 인수에 대한 참조에 대한 값을 보유하는 데 사용되는 객체) : 수명은 사용에 따라 결정된다. 참조에 바인딩된 경우 수명은 참조의 수명이다. 그렇지 않으면, 그것들은 그들이 속한 완전한 표현식이 끝날 때까지 살아 있다. 전체 표현식은 다른 표현식의 일부가 아니다. 일반적으로 임시 객체는 Automatic이다.
- Thread-local objects (즉, thread_local로 선언된 객체) : 이러한 객체는 해당 thread가 만들어질 때 생성되고 thread가 존재할 때 소멸된다.
Static과 Automatic은 전통적으로 storage class라고 한다. 배열 요소와 비정적 클래스 멤버의 수명은 객체에 의해 결정된다. 그들은 그 일부다.
'Program Language > C & C++' 카테고리의 다른 글
[C++] 포인터(Pointer) (0) | 2021.12.23 |
---|---|
[C++] 별칭 (0) | 2021.12.16 |
[C++] decltype 지정자 (0) | 2021.12.16 |
[C++] auto 지정자 (0) | 2021.12.16 |
[C++] 데이터 타입 (bool, char, integer, floating) (0) | 2021.12.16 |