1. rand() : 난수 생성기
0~32767 범위 내 랜덤 한 숫자를 반환해 주는 함수.
한번 정해진 숫자는 그대로 계속 동일한 숫자가 나오므로 초기 시드 값을 초기화해주어야 한다.
srand() : 초기 시드 값을 초기화하는 함수
보통 time()을 넣어 현재 시간을 기준으로 초기 시드 값을 초기화한다.
srand(time(0));
rand() % 원하는 범위 숫자
rand() % 12 //0~11까지의 숫자가 나온다.
rand() % 12 + 1 // 1~12까지의 숫자가 나온다.
실제 상용 서비스에서는 나올 확률이 상이하여 사용할 수 없다.
2. 문자열
'' : 문자 하나
"" : 문자 한 개 이상
C언어에는 문자열이 따로 존재하지 않는다.
그래서 char 배열을 선언하여 여러 char를 담는 용으로 사용한다.
C++에서는 string이라는 class로 사용된다.
char H[10] = {'H', 'e', 'l', 'l', 'o'};
char M[10] = {"Hello"}
for(int i = 0; i < 5; ++i)
{
cout << H[i] << endl;
}
출력결과 : Hello
우리가 배열 M으로 작성해도 컴퓨터는 H와 동일한 방식으로 인식한다.
배열의 크기를 출력해보면 실제 글자수 + 1 인 것을 알 수 있는데 마지막 글자 다음에 ‘\0’ 문자가 들어가 있어서 그렇다.
해당 문자열의 끝을 알기 위해 들어간 문자다.(Escape 문자)
char h[5] = {'h', 'e', 'l', 'l', '0', 'a'}
위와 같이 기재한 후 출력할 경우 마지막 ‘\0’이 지워지기 때문에 Escape 문자가 나올 때까지 연속된 메모리를 읽어오는 오류가 발생한다. 물론 자료형이 char일 경우에만 문자열로 출력한다.
Escape 문자와 유사한 문자들
\t : Tap 키
\b : Backspace 키
\n : Enter
아스키 코드에 포함되지 않은 글자, 특수문자들은 1Byte가 아니기 때문에 추가로 메모리를 잡아야 한다.
C++의 String은 Class로 문자열을 출력하는데 주로 사용된다.
<iostream> 안에 <string>이 포함되기 때문에 따로 Include 해주지 않아도 되지만, 정석적으로는 해주는 게 좋다.
해당 Class는 Operator + 도 구현되어 있어 문자를 합칠 때도 용이하다.
또한, 한글도 사용가능하다.
* #include
. h : C 언어 표준 header file
. h가 없는 경우 : C++ 표준 header file (Class)
<> : 컴파일러가 설정한 디렉터리를 찾아서 있다면 쓰라는 의미
" " : 컴파일러가 설정한 디렉토리 + 내가 설정한 header file까지 찾아서 있다면 쓰라는 의미.
3. 동적할당
Run Time에서 쓸지 안 쓸지가 정해지는 데이터의 경우는 동적할당하는 게 훨씬 효율적이다.
C++에서는 new, C에서는 malloc 키워드를 사용한다.
int* Abb = new int;
delete Abb;
Abb = nullptr;
new 키워드는 반환 값이 메모리의 주소값이기 때문에 포인터를 이용하여 값을 받아야 한다.
동적 할당 시 메모리 해제를 해주지 않으면 계속 메모리가 잡혀 있어 누수가 발생하므로, 반드시 delete를 작성해주어야 한다.
다르게 생각하면 내가 원할 때 해당 메모리를 지울 수 있다는 것이 된다. 내가 쓸지 안쓸지 모르는 메모리를 계속해서 잡아놓고 있는 것보단, 동적 할당을 통해 그때 잡아주는 것이 성능에 훨씬 도움이 된다.
메모리가 해제된 포인터는 nullptr로 초기화해주어야 댕글링 포인터가 되지 않는다.
언리얼 내에서 Object를 배치할 때 해당 Object가 생성되므로 new와 같이 동적할당을 통해 메모리를 잡아준다.
다만, 언리얼에서는 new 대신 newobject라는 다른 키워드를 사용한다. new도 결국 자료형이므로, 배열을 만들 수 있다.
이를 동적배열이라고 한다.
* 댕글링 포인터
이미 해제된 주소값을 계속해서 가리키고 있는 포인터
메모리 접근 시 예측 불가능한 동작, 잠재적 보안 위험 등을 유발한다.
int* Abb = new int[10];
delete[] Abb;
Abb = nullptr;
동적 배열 사용 시 delete []를 사용해야 한다.
배열인데 delete을 사용할 경우 배열의 첫 번째 인덱스 값만 초기화되기 때문에 뒤에 나머지 메모리는 사용할 수 없게 된다.
배열이 아닌데 delete []를 사용하는 경우 어떤 데이터가 들어가 있을지 모를 뒷 메모리까지 모두 지워버리기 때문에 Error가 발생한다.
현업에서는 너무 위험하기 때문에 일반 포인터 사용을 잘하지 않는다.
대신에 스마트 포인터를 주로 사용하게 된다.
* 스마트 포인터
메모리의 해제를 자동으로 해주는 포인터
<memory>를 Include 해야 하며 std::unique_ptr <자료형> smart_ptr(new 자료형(데이터));로 선언한다.
보다 안전하게 포인터를 사용하기 위해선 아래와 같이 A 포인터가 Nullptr(0)이 아닌지 확인해 가며 사용하는 것이 좋다.
언리얼에서는 Is Valid라는 함수를 통해 검사한다.
int Size = 5;
int* Numbers = new int[Size];
for(int i = 0; i < Size; ++i)
{
Numbers[i] = i + 1
}
int* Temp = new int[Size + 1];
for(int i = 0; i < Size; ++i)
{
Temp[i] = Numbers[i];
}
Temp[Size] = Size + 1;
delete[] Number;
Numbers = Temp;
Temp = nullptr;
위는 특정 size를 갖는 동적 배열을 만드는 코드이다.
배열은 처음 만들어질 때 크기를 가져야 하므로 더 크게 만들고 싶다면, 더 큰 배열을 새로 만들어서 가리키는 주소값을 바꾸는 식으로 구현할 수밖에 없다.
언리얼 엔진에서는 TArray Class로 구현되어 있다. C++ 표준 라이브러리에도 vector로 구현되어 있다.
4. 구조체
자료형을 묶어서 내가 원하는 자료형을 만드는 것. Custom Data Type이다.
struct Actor
{
int X;
int Y;
};
구조체도 결국 자료형이기 때문에 다른 구조체의 멤버로 들어갈 수 있다. 그렇다면 구조체의 크기는 어떨까?
기본적으로 컴퓨터는 가지고 있는 내부 멤버의 크기 중 가장 큰 크기를 기준으로 자른다.
Ex)
int A, int B, char C : 12Byte
longlong A, char B, int C : 16Byte
char A, char B, char C, int D : 8Byte
struct Vector2D
{
int X;
int Y;
};
struct Actor
{
vector2D Actor_;
char Shape;
};
Actor User[100] = {};
//동적할당
Actor* Player = new Actor;
*(Player).Position.X = 10 == Player->Position.X = 10;
구조체로 배열을 선언할 수도 있다. 구조체 내부의 멤버에 접근하기 위해선. 을 사용한다.
실제로는 동적 할당을 하기 때문에 포인터로 받아오는 게 맞으며, 포인터로 받아온 해당 구조체 내부 멤버에
접근하려면 *(포인터명). 내부멤버로 쓰면 되지만, 이를 간단하게 화살표로 표현할 수 있다.
포인터명→내부멤버
기타
- \n과 endl;의 차이
- endl; : 끝났으니까 바로 출력하라는 의미
- \n : 메모리에 저장해 놨다가 출력을 한 번에 진행
- 문자열이 컴퓨터에서 가장 느리다. 그래서 언리얼 엔진에는 상황에 맞춰서 쓰도록 name, String, Text(UI용) 구현되어 있다.
- 댕글링 포인터와 비슷한 사례로 함수내에서 새로운 포인터를 선언하여 그 포인터로 함수내 코드를 진행하는 경우 받아왔던 포인터는 날아가버린다.지우거나 수정하는 함수일 경우 반드시 기재하여야한다. 작업 시 인자로 포인터를 받는 경우 받은 포인터 내 데이터를 지우거나 수정하지 않는 것이 통상적이다.
- 구조체내에서 멤버에 접근하거나 함수를 쓰는 경우 사실 this 포인터가 생략되어 있다.
'C++ > 문법' 카테고리의 다른 글
File Input Output & Delta Time (0) | 2024.11.07 |
---|---|
Inline & Switch case문 (8) | 2024.11.06 |
Class 와 Template (0) | 2024.10.31 |
C++ 기본 문법(변수와 함수) (0) | 2024.10.23 |
C++ 기본 문법(연산자, 배열) (1) | 2024.10.18 |