본문 바로가기

스터디/C++

auto,decltype,nullptr,std:array

auto -> 자동 형 (var 같은)

컴파일 타임 때 추론되어야 함.


decltype(i) j = 5    //  j 의 형태를 i 의 형태로 선언.

decltype(i+j) k = 10; // k 의 형태를 i+j 의 형태로 선언.


--> 함수의 형에도 사용 가능함.


auto add(T1 a, T2 b) -> decltype(T1+T2)   

// decltype 의 사용처 (리턴해야할 타입을 모를 때)

{

......

}


->  는 타입을 지정해 주는 연산자중 하나.

(람다를 위해 생김)


nulltype 은 값.

nulltype 의 type 이 nulltype_t


nullptr =/= nullptr_t


이제 int a = nullptr 안됨


std:array 는 일반적으로 쓰는 배열 대신에 나온건데,

일반적 배열에서 사용하는 기능이 추가됨. (swap, 등)

--> 하지만 다차원 배열 사용에 약간 까다로움.

--> 그냥 배열을 사용하다가 바로 사용을 하면 약간 어색함



R-value L-value

(쉽게 말해서 L 밸류는 변수, R 밸류는 상수)


L 밸류는 그 줄이 끝나고 사라지지 않는 값

move semantics, perfect forwarding 에 사용됨.


Move Semantics

 

1
2
std:string s="Hello", t="world";
std:string u=s+t;
cs

이런 소스 코드가 있을 때, s+t 의 임시객체가 만들어지고, u 에 복사되었는데

이 때 move 를 사용해서 임시객체가 복사되지 않고 이동된다.

(불필요한 복사를 막음)



std::move

L value 나 R value 둘다 R value 로 바꿔준다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person {
private:
    std::string name;
public:
    void setName(std::string&& Name){
        this->name = name;
    }
    
}
 
int main() {
    Person minsu;
    minsu.setName("Minsu")
    
}
cs


이 때, setName 함수에서 R-value Reference 로 Name 을 받는데,

(R-value Reference 는 L-value)

this->name = name; 

할 때 L-value = L-value 가 되어 "복사"가 일어난다.

따라서 이런 불필요한 복사를 막기위해 move 를 사용한다.

std::move 로 

L-value = R-value 로 바꿔줌 으로써 "이동"이 일어나게 한다.

--> 성능상의 이점을 얻을 수 있다.



Ex) 함수에서 인자값을 받을 떄,

L-value 로 받아지는데, std::move 를 사용하면 

L-value = L-value 를

R-value 로 사용함으로써

L-value = R-value 로 바꿔줄 수 있음. (복사를 막아줌) 


Perfect Forwarding 


&& 는 두가지 의미가 있는데,

1. R-value 레퍼런스. (이 때 R-value 는 L-value이다 실행 후 값이 남아있으므로.)

2. 템플릿에서 템플릿 type 에 사용할 때. (퍼펙트 포워딩 때 이런 의미로 사용)

3. auto type 뒤에 사용할 때.


--> 이 때 2,3 경우 일 때만 R-value와 L-value 둘다 될 수 있는 것을 

Universal Referense 라고 함.

이외의 && 은 R-value Reference 임!!!!





함수에서 값을 받을 때는, 원래 L-value 로만 받았었는데

C++ 11 에서 부터 R-value 가 생김으로써 template 에서 R-value 를 어떻게 받는 지에 대한 문제가 생김.

--> 따라서 이 문제를 해결하기 위해 Universal Reference 가 생김.


R-value Reference 는 L-value


Reference Collapsing Rules

   Reference 경합    Reference 붕괴

   T& &              T&

   T& &&            T&

   T&& &           T&

   T&& &&          T&&



template <typename T>

/*

L-value = T&

R-value = T

*/

void f(T&&){

// return a; 대신에

std::forward(a); // Perfect Forwarding

}


std:forward 는 L-value 는 L-value, R-value 는 R-value 로 변환 시켜주는데,

이 때 R-value 가 L-value 로 나가지 않게 하기 위해서 forward 를 사용한다.


이것들을 종합해서 Perfect Forwarding 이란,

1. L-value 와 R-value 를 동시에 받을 수 있고,

2. L-value 로 들어온 건 L-value 로 리턴되고 R-value 는 R-value 로 리턴되는 것


Perfect Forwarding 이라고 한다.




캐스팅(Casting)

const casting

const int --> int 로 사용할 때

const casting 을 사용한다.

Ex) 라이브러리에서 Const int 형인데, int 으로 사용할 때 사용한다. (라이브러리 자체가 불가능 하므로)


reinterpret_cast 

모든 형태를 임의의 형태로 변경해줄 때 사용.

하지만 동작을 보장하지 않음. 정말 드물게 사용

손건: "C언어가 그리울 떄 사용해.."



static cast 와 dynamic cast 는 나중에 정리...