336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
1.
일반적으로 C에서는
lvalue를 = 의 좌측을 의미한다. (예) int a = 10; 이라고 하면 a 가 lvalue
그런데, 사실 lvalue는 = 를 기준으로 좌측 우측 모두 올 수 있다.
아래 예제를 보게 되면 v1은 lvalue이다. 그런데 v2 = v1; 에서 보는거와 같이 우측에도 올수 가 있다.
결국 좌측 우측이 기준이 아니라 lvalue는 다음과 같이 정의할 수 있다.
1. 이름이 있다. (int a = 10; => a 라는 이름이 있다.)
2. 지속성이 있다. (메모리 어딘가에 저장되어 있고 block이 다른곳에서 사용 가능하다)
3. 주소를 얻을 수 있다. (&a)
아래 goo 함수 또한 reference를 return 하는데 이것도 lvalue이다.
위 const 또한 lvalue 이지만 변경 불가능한 lvalue 이다.
#include2.using namespace std; int x = 0; int foo() { return x; } int& goo() { return x; } int main() { int v1 = 0, v2 = 0; v1 = 10; // v1 : lvalue, 10 : rvalue // lvalue는 좌측 우측 모두 올수 있다. v2 = v1; 10 = v1; foo() = 10; // foo 는 값이 리턴됨(0 : 문법적으로는 임시객체임) // 값을 리턴하는 함수는 rvalue. error goo() = 10; // goo 는 진짜 x가 리턴됨 // 참조를 리턴하는 함수는 lvalue int* p1 = &v1; int* p2 = &10; // rvalue는 주소를 얻을 수 없다. error // lvalue는 이름이 있지만 rvalue는 이름이 없다 // lavlue는 지속성을 가지지만, rvalue는 지속성이 없다. // *임시객체는 rvalue 이다. constexpr int c = 10; c = 20; // ?? c는 rvalue ? lvalue? // 이름이 있고 메모리 지속성도 있고, 메모리 주소도 찍을 수 있다. // lvalue이기는 하지만 변경이 불가능한 lvalue 이다. // constant vs literal constexpr int c1 = 10; cout << &c1 << endl; // c1은 constant : lvalue cout << &10 << endl; // 10 은 literal : rvalue }
int main() { int n1 = 10; // C++98의 참조 int& r1 = n1; // ok.. lvalue는 참조 가능 (이것을 lvalue reference라고 부름) int& r2 = 10; // error. // C++98 const 참조 const int& r3 = n1; // ok const int& r4 = 10; // Const 참조는 lvalue 뿐만 아니라 rvalue도 가르킬수 있다. ok // C++11 rvalue reference - rvalue만 참조 가능 int&& r5 = n1; // error int&& r6 = 10; // ok }3. 그동안 reference라고 불렀던 것은 실제로 lvalue-reference임.
int main() { int n1 = 10; // C++98의 참조 int& r1 = n1; // ok.. lvalue는 참조 가능 (이것을 lvalue reference라고 부름) int& r2 = 10; // error. // C++98 const 참조 const int& r3 = n1; // ok const int& r4 = 10; // Const 참조는 lvalue 뿐만 아니라 rvalue도 가르킬수 있다. ok // C++11 rvalue reference - rvalue만 참조 가능 int&& r5 = n1; // error int&& r6 = 10; // ok }4. Reference 충돌
typedef int& LR; typedef int&& RR; // Reference Collapse : 양쪽이 모두 && 일때만 && 되고, 나머지는 & 이다. int main() { int n = 10; LR r1 = n; // n ? 10 RR r2 = 10; LR& r3 = n; // LR& => int& & => int& // 양쪽이 1개(&) 이므로 결국은 1개이다. RR& r4 = n; // RR& => int&& & => int& // 2개 1개 이므로 결국 1개 LR&& r5 = n; // & && -> & RR&& r6 = 10; // && && -> && // int && && a = 10; 직접 타이핑해서는 안된다. typedef를 이용해서 충돌나는 경우에만 가능함 }
왜 이런 복잡한 규칙과 문법을 만들었을까?
이걸 이해 하려면 perfect forwarding을 알아야 한다.
'ⓟrogramming > C++' 카테고리의 다른 글
Visual Studio 에서 Boost 사용법 (0) | 2016.07.28 |
---|---|
임시객체 (1) | 2016.05.11 |
static_assert (0) | 2016.05.10 |
부분전문화(partial specialization) template (0) | 2016.05.10 |
Inserting object to C++11 vector without copy constructor (0) | 2015.08.29 |