공부/Unity

24.04.24

월러비 2024. 4. 25. 20:26

새로 생성한 스크립트

  • DynamicCast : 소멸자 순서 확인 / 상속받은 클래스의 소멸자 확인
  • Inline : 선언부와 정의부를 따로 생성하지 않고 선언 및 정의를 바로하는 문법 확인
  • Template : 템플릿 함수 예시 / 템플릿 특수화 함수 예시(매개변수에 자료형 넣고 실행) / 템플릿 포인터 예시
  • TemplateClass : 템플릿 클래스 생성 / 템플릿 클래스 상속 예시
  • Stack_Template : 템플릿으로 스택 생성

 

  • 람다 캡쳐절
auto add = [&]()//var 역할을 하는 자료형인데 지역 변수 아니면 사용하면 안된다. / []안의 내용을 함수로 쓸 수 있다. / &는 이름이 없으니 '익명함수'가 된다.
{
	printf("a = %d, b = %d\\n", a, b); //[] 안에 쓰인것만 쓰겠다는 뜻이다. / 아무것도 안적으면 아무것도 안쓰겠다는 의미다. / [&]는 모든 변수를 레퍼런스로 쓰겠다는 의미다. / *은 모든 변수의 값을 쓰겠다는 뜻이다. / [a, b]는 위의 a와 b 값을 복사해서 쓰겠다는 의미다. / ()안에 쓰면 매개변수를 받아서 쓰겠다는 의미다.
	printf("&a = %p, &b = %p\\n", &a, &b);
	return a + b;
};
  • 스레드 람다 사용
std::thread t([=](int x)
{
	for (int i = 0; i < x; i++)
	{
		printf("%d\\n", i);
	}
}, b); //이전 C++ 람다 했을때 function을 확인하면 같은 형태이니 확인이 가능하다.
t.join();
  • function 람다
    • 함수포인터 람다
    function<int(int)> GetAdd() //<리턴형(파라미터 형태)> / function<int(int)> = 이거 자체도 자료형이다. / 리턴 타입을 함수로 할 수도 있다.(지금 하는게 그거다)
    {
    	member += 10;
    
    	return [=](int value)
    	{
    		return value + member;
    	};
    }
    

auto 키워드

  • 컴파일러가 선언된 변수 또는 람다 식 매개 변수의 초기화 식을 사용하여 해당 형식을 추론하도록 지시
    • 즉, C#의 ‘var’와 비슷한 역할을 하고 있다.
  • 반복자(iterator)(for 등)에 쓰는것은 나쁘지는 않다.
  • 가능하다면 auto를 남발하지않고 실제 자료형 타입을 사용하는 것이 좋다.
    • 오류생겼는데 auto면 찾으러 돌아다녀야 하기 때문이다.
    단점
    • 포인터를 사용할때 값 형태인지 포인터 형태인지 알 수가 없어 가독성이 좋지 않다. ⇒ auto*처럼 사용할 수 있다. (포인터를 받을 때 선언)
    • 마찬가지로 auto&처럼 사용할 수 있다. (참조를 받을 때 선언)

 

  • 함수포인터 람다 결과 확인
auto func2 = lambda->GetAdd2(30);
int f = func2(20);
printf("f + %d\\n", f); //member원래 값 10 + 매개변수값 30 + 리턴 함수의 매개변수값 30 = 70이 나온다.

다이나믹 캐스트

  • 다이나믹 캐스트는 ‘가상화’가 되었을때만 사용이 가능하다.
  • 런타임에서 이게 자식클래스에 가상화가 되는지 확인하기 위해? 사용한다.
  • RTTI (런타임 어쩌고에 포함되어있다) → 다이나믹 캐스트 말고 3개가 더 있다.

가상화

  • 가상 함수가 ‘하나 이상’있어야 가상화가 가능하다. (가상화 조건 외워둬야 한다.)
  • 다운 캐스팅을 체크하려면 가상화가 일어나야한다.
  • 가상화 했을때는 ‘소멸자도 가상화’를 해줘야한다.

함수의 실행 순서

int Test(int a)
{
	int c = 20;
	return a + c + 10;
}
int b = Test(10; //Test(10)주소
  1. int b의 주소 생성
    1. 10을 넣어서 넘긴다.
  2. Test를 넣는다.
    1. Test를 사용해야하니 코드를 ‘점프’ 할 주소를 꺼낸다.
  3. Test 요소 접근 → 저장된 Test 주소 꺼낸다.
  4. 10 저장 공간 꺼내서 사용
  5. a 공간 생성 = 10 저장
  6. C 공간 생성 = 20 저장
  7. a와 c를 사용하여 리턴 ⇒ 40 메모리 이외로 ‘임시 공간에 저장한다.
    1. 리턴하면 ‘지역 변수’는 전부 삭제된다. ⇒ a와 c 공간 삭제
  8. b로 돌아갈 주소 꺼낸다.
  9. 임시 공간에 저장된 40을 저장한다.

기타

  • ESP , EBP , EIP(다음에 실행할 명령의 주소를 가진다) : 셋다 32비트다. (E : Extended)
    • 원래 위의 3개는 원래 16비트 / 8비트의 컴퓨터 용량에서 생성되었다.
    • 16비트는 2바이트이고 65536바이트이니 64킬로 바이트여서 이것을 640킬로 바이트로 늘려쓰기 위해 ‘Extend’라는 개념이 생겼다.
  • 지금은 64비트를 사용하고 RSP, RBP, RIP (Regist?)를 사용하고 있다.

 

함수 호출 순서

  1. 공간 생성
  2. 값 저장
  3. 점프해야하면 주소 꺼내고 점프명령 실행
  4. ESP는 스택이 쌓일수록 같이 움직인다.
    1. EBP는 -1 위치에서 계속 다린다.
    2. EIP는 임시공간에서 계속 명령을 받아서 실행한다.
    3. 스택은 쌓일때는 top먼저 이동하고 저장하고, 뺄때는 먼저 뺀 다음 top을 내린다.
  5. ESP와 EBP가 같이 -1이 된다면 스택 포인트 공간을 삭제한다. (함수의 실행이 끝났다)

Inline 함수

  • 인라인 함수는 위의 함수 실행과 같지 않다.
    • 함수 호출 때 컴파일이 함수 내용을 가져온 뒤 실행한다.
    • 스택 포인트가 생성되지 않는다.
    • 즉, 점프하지 않고 실행한다.
    • 용량이 커진다는 단점이 있다.
  • 인라인이 되는 조건 
    • ESP : 함수가 진행하고 있을 때 stack의 제일 아래 부분, 현재 진행 stack 지점, Stack Pointer stack 메모리는 아래로 성장하기 때문에 제일 아래가 제일 마지막이 된다.
      • 즉, 스택에 데이터가 이동하면 같이 이동하는 지점이다.
    • EBP : 스택의 가장 윗 부분(기준점), Base Pointer
      • 즉, 초기 위치와 같고 ESP와 같아지면 스택이 비어있는 상태이니 스택 포인트가 삭제된다.
    • EIP : 실행할 명령의 주소다. → Instruction Pointer
  • EBP, ESP, EIP

 

Template

template<typename T>
void Add(T a, T b)
{
	
}
Add<int>(10, 20); //인라인처럼 함수를 복사해서 점프하지 않고 실행한다.
void Add<T>(T a, T b)
{

}
Add<int>(10, 10); //C#도 함수를 복사해서 점프하지 않고 실행한다.
  • 함수
template<typename T>
void Print(T data)
{
	cout << "템플릿 함수 : " << data << endl;  //cout : 콘솔로 아웃 시킨다는 의미다. / << : 스트림 기호
}

int i = 10;
Print<int>(10);

string s = "Atents";
Print<string>(s);
  • 특수화
template<>
void Print(float data) //매개변수가 float형이면 이게 실행된다.
{
	cout << "템플릿 특수화 함수 : " << data << endl;
}

template<typename T>
void Print(T* data) //포인터도 가능하다.
{
	cout << "포인터 : " << *data << endl;
}

float f = 3.14f;
Print<float>(f);

int* p = &i;
Print<int>(p);
  • 클래스
template<typename T>
class Character
{
public:
	void Set(T name)
	{
		this->name = name;
	}

	void Print()
	{
		cout << "name : " << name << endl;
	}

	virtual void PrintName() = 0; //순수 가상 함수 : 추상클래스가 된다. => Character는 객체 생성이 불가능해진다.

protected:
	T name;

};

Character<string> character;
character.Set("Oak");
character.Print();
  • 상속
class Player : public Character<int>
{
public:
	void PrintName() override //이거 재정의 안하면 얘도 추상으로 만들어야한다.
	{
		cout << "Player : " << name << endl;
	}
};

class Monster : public Character<string>
{
public:
	void PrintName() override //이거 재정의 안하면 얘도 추상으로 만들어야한다.
	{
		cout << "Monster : " << name << endl;
	}
};

Player player; //얘는 <int>로 고정을 시켜서 템플레이트를 안써도 된다.
player.Set(100);
player.PrintName();

Monster monster; //얘는 <ㄴㅅ갸ㅜㅎ>로 고정을 시켜서 템플레이트를 안써도 된다.
monster.Set("Oak");
monster.PrintName();
  • 스택
#define MAX_STACK_COUNT 20 //스택 최개 개수

template<typename T>
class Stack
{
public:
	Stack()
	{
		memset(values, 0, sizeof(T) * MAX_STACK_COUNT); //memset : 메모리를 셋 하는데 (시작주소, 뭘로 설정할거냐, 배열 초기화 갯수) => C++ 의 배열 초기화 방법
	}

	void Push(T value)
	{
		assert(top + 1 < MAX_STACK_COUNT); //top + 1이 스택 최대 갯수보다 작은지 확인해야한다.

		values[++top] = value; //top를 먼저 올려서 배열공간이 남았는지 확인하고 넣어야한다.
	}

	T Pop() //얘는 요소를 뺄거니까 반환하는 자료형이 뭔지 모르니 T로 한다.
	{
		assert(Empty() == false);

		T val = values[top--]; //먼저 요소를 빼고 top를 내려야한다.

		return val;
	}

	T Front()
	{
		return values[top]; //리턴만 만들고 확인하는 용도로 사용한다.
	}

	bool Empty()
	{
		return top < 0 ? true : false; //0보다 작으면 비어있으니 true 아니라면 들어있으니 false다.
	}

private:
	int top = -1; //top of point 라고 한다.

	T values[MAX_STACK_COUNT]; //스택 요소들을 저장할 배열
};

Stack<int> stack;
stack.Push(10);
stack.Push(20);
stack.Push(30);

stack.Pop();

stack.Push(40);
stack.Push(50);

while (stack.Empty() == false)
{
	printf("%d\\n", stack.Pop());
}

순수 가상 함수

virtual void PrintName() = 0;
  • 이렇게 virtual이 붙은 선언 방식을 ‘순수 가상함수’라고 부른다.
    • 이렇게 선언된 순수 가상 함수가 있는 클래스를 ‘추상클래스’라고 부른다.
  • 이게 선언된 클래스를 상속받은 자식 클래스는 ‘반드시’ 순수 가상함수를 override 해서 재정의 해줘야한다.

'공부 > Unity' 카테고리의 다른 글

24.04.29  (0) 2024.04.30
24.04.25  (1) 2024.04.25
24.04.23  (0) 2024.04.24
24.04.22  (0) 2024.04.22
24.04.19  (0) 2024.04.22