모던 c++입문 정리
변수
리터럴
- 리터럴정수는 자릿수에 따라 int, long, unsigned long 타입으로 취급된다.
- 소수나 지수(3e12 등)는 double 타입으로 취급된다.
- 접미사를 붙이면 리터럴 타입을 지정해줄 수 있다. 2(int) 2u(unsigned) 2l(long) 2ul, 2.0(double) 2.0f(float) 2.0l(long double)
- c++14부터 추가된 string 지정자도 있다. 없으면 const char* 로 만들어진다. ex) "test"s
- 0b로 시작하면 2진수, 0으로 시작하면 8진수, 0x로 시작하면 16진수로 해석된다.
- 길이가 긴 리터럴 가독성 향상을 위해 ' 로 숫자를 분리할 수 있다. ex) long d = 6'546'687'616'861'129l; int b = 0b11'0011'1010;
- 길이가 긴 문자열은 여러개의 부분 문자열로 나눌 수 있다.
#include <string>
std::string s = "This is a very long and clumsy text"
"that is too long for one line.";
리터럴의 주의점
1. 표준라이브러리에서 복소수 타입을 지원하는데, float 과의 연산만 지원한다.
std::complex<float> z(1.3, 2.4)
// => 1.3 + 2.4i
z * 2.0 // 리터럴이 double형이라 불가능
z * 2.0f // 접미사를 붙여서 리터럴을 float화 했다
2. 오버로딩한 함수에 0을 전달하게되면, int인지 float인지 모호하다. 0u 처럼 리터럴에 접미사를 붙여 확실히 표현할 수 있다.
3. 소수나 지수는 double 타입이라, long double타입으로 작업할 경우 정확도가 떨어질 수 있다.
long double ld = 0.3333333333333333333; // 자릿수를 잃어버린다.
long double ld = 0.3333333333333333333l; // 리터럴을 long double로 지정해서 값 손실이 없다.
중괄호 초기화
중괄호를 사용해서 변수를 초기화하는 경우, 자동 형변환이 발생하면서 값의 손실이 올때 컴파일 에러가 발생한다.
* 참고로 c++11 부터 만들어진 규칙이기 때문에 g++ -std=c++11 옵션을 사용해야한다. 없으면 그냥 초기화된다.
float f = {1.15l}; // 정상작동. 더블 리터럴이라서 오류날줄 알았는데 안나네
double d = 1.15;
float f = {d}; // 축소오류. double 변수에 넣었다가 float에 넣기 때문
int i = -10;
unsigned long ul = {i}; // 축소오류. 음수를 표현할 수 없기 때문
// Cls::Cls(int);
Cls t{1.5}; // 축소오류. 인트형 타입을 받는 생성자이기 때문
범위
변수와 상수의 수명을 결정
전역변수는 소프트웨어가 커질수록 수정사항을 추적하기 어려워지기 때문에 사용하지 않는것이 좋다. (전역상수는 ㄱㅊ)
지연변수는 선언된 블록안에서만 사용할 수 있다. 외부 블록에 있는 동일한 이름의 변수는 숨겨지며 네임스페이스를 이용해 접근할 수 있다.
static 변수는 프로그램이 끝날때까지 살아있지만, 범위 안에서만 보인다.
연산자
Lvalue : 주소를 지정할 수 있는 항목. ex) 변수, const로 선언된 변수형 상수, ++a 연산 등 (a++은 아님)
Rvalue : 표현식이 종료된 이후 사라지는 임시적인 값 ex) 연산결과, 리터럴 등
주소 참조 연산(*)은 Rvalue, Lvalue 상관 없이 인자로 받아주지만 결과는 Lvalue가 된다.
주소 반환 연산(&)은 Lvalue를 인자로 받고, Rvalue를 리턴해주는 연산이다.
함수 리턴값은 리턴 타입이 참조(int& func())인 경우에만 Lvalue이다.
Lvalue의 참조는 & Rvalue의 참조는 && 이지만, Rvalue를 const int& 같이 상수화 하면 바인딩할 수 있다.
연산자의 결합 방향과