6월, 2022의 게시물 표시

220629) Smart Pointer

스마트 포인터(smart pointer) C++ 프로그램에서 new 키워드를 사용하여 동적으로 할당받은 메모리는, 반드시 delete 키워드를 사용하여 해제해야 합니다. C++에서는 메모리 누수(memory leak)로부터 프로그램의 안전성을 보장하기 위해 스마트 포인터를 제공하고 있습니다. 스마트 포인터(smart pointer)란 포인터처럼 동작하는 클래스 템플릿으로, 사용이 끝난 메모리를 자동으로 해제해 줍니다. 보통 new 키워드를 사용해 기본 포인터(raw pointer)가 실제 메모리를 가리키도록 초기화한 후에, 기본 포인터를 스마트 포인터에 대입하여 사용합니다. 이렇게 정의된 스마트 포인터의 수명이 다하면, 소멸자는 delete 키워드를 사용하여 할당된 메모리를 자동으로 해제합니다. 따라서 new 키워드가 반환하는 주소값을 스마트 포인터에 대입하면, 따로 메모리를 해제할 필요가 없어집니다. 스마트 포인터의 종류 C++11 이전에는 auto_ptr이라는 스마트 포인터를 사용하여 이 작업을 수행하였습니다. 하지만 C++11부터는 다음과 같은 새로운 스마트 포인터를 제공하고 있습니다.   1. unique_ptr 2. shared_ptr 3. weak_ptr   스마트 포인터는 memory 헤더 파일에 정의되어 있습니다. --- unique_ptr unique_ptr은 하나의 스마트 포인터만이 특정 객체를 소유할 수 있도록, 객체에 소유권 개념을 도입한 스마트 포인터입니다.   이 스마트 포인터는 해당 객체의 소유권을 가지고 있을 때만, 소멸자가 해당 객체를 삭제할 수 있습니다. unique_ptr 인스턴스는 move() 멤버 함수를 통해 소유권을 이전할 수는 있지만, 복사할 수는 없습니다. 소유권이 이전되면, 이전 unique_ptr 인스턴스는 더는 해당 객체를 소유하지 않게 재설정됩니다. -...

220621) Space(Matrix), view, projection, NDC, viewport

이미지
Space (Matrix적 의미) 오브젝트를 '공간'에 잡아두기 위한 행렬을 일컫는다. 모든 오브젝트는 각자 ' SRT Transform' 이 포함된 고유의 Space를 가지고 있는데, 하나의 오브젝트를 구성하는 작은 부품들은 Local Space 를 중심으로 구성되어있으며, 구성된 오브젝트는 장면을 구성하는 World Space 를 중심으로 배치될 위치가 결정된다. 장면이 완성되면 View Space 에서 장면 내 오브젝트들을 바라보는 시선(방향)이 결정되며, Projection Space 를 통해 우리들의 눈에 어떻게 투영될 지를 결정한다. 이렇게 완성된 Clip Space 는 Viewport 변환을 통해 어디까지 윈도우에 표현할 지를 결정할 수 있다. --- View Matrix World Space 를 바라볼 위치를 결정하는 행렬이다. View Matrix 는 카메라에 비유되고, View Space 는 카메라로 바라본 세계에 해당한다. --- Projection Matrix 카메라로 바라본 세계를 어떻게 투영할 지를 결정하는 행렬이다. Projection하는 방법으로는 크게 ' Orthographic projection', 'Perspective projection' 이 있다. Perspective : 원근법이 적용되는 3D 화면에서 주로 사용됨. Orthographic : 직각 투영, 원근법이 없는 2D 화면에서 주로 사용됨. --- NDC (Normalize Device Coordinate) [Clip Space] 사용자가 모니터 속 게임의 화면을 볼때, 3D로 이루어진 공간이 렌더링을 통해 2D로 변환된 화면을 바라보게 되는데, 이것을 투영이라 부른다. 이때, 사용자가 모니터에 비친 2D의 상을 바라봤을 때 2D투영 평면이 가지는 좌표계를 NDC , 또는 Clip Space 라고 한다. 위 사진처럼 [-1~1]의 범위를 가진다. --- Viewport Clip Space를 모니터에 표시하기 ...

220610) SRT Transform, 벡터, 내적과 외적

이미지
 SRT Transform 좌표계 내 객체의 크기(Scale), 각도(Rotation), 이동(Translation)의 변환을 도와주는 행렬을 뜻한다. 위 사진은 Homogeneous 2D 좌표계에서 변환을 할 경우의 변환행렬 계산식을 나타낸 것이며, 좌표 p = [x,y,1]이 있다고 할 때(p의 3번째 원소는 상수 w), [p' = (T · R · S) · p] 꼴로 표현하여 변환된 좌표 p'를 구한다. ----- 3D에서의 Transform 출처:  http://dolphin.ivyro.net/file/directx8.0/tutorial09.html 3차원 좌표계의 변환행렬은 4x4 꼴로 계산한다. 이때, 변환행렬에 대한 SRT행렬 곱셈순서는 DirectX와 OpenGL 사이에서 차이가 발생한다. DirectX는 왼손 좌표계를 사용하고(p · SRT), OpenGL은 오른손 좌표계(TRS · p)를 사용하기 때문이다.  둘은 서로 전치행렬이므로 변환에 대한 결과 값은 동일하다. DirectX 에서의 3차원 회전변환 행렬은 다음과 같다. (OpenGL의 경우는 위 행렬을 전치행렬로 바꾸면 된다) 벡터 : 방향과 크기를 나타낸 것. 앞 좌표가 원점이면 끝점값만으로 벡터를 표현할 수 있다. 벡터 합연산 : 두 벡터의 값을 합한 값. A+B일때 아래의 법칙 중 하나를 사용해 결과값 C를표현할 수 있다. 벡터의 실수배 : 벡터에 실수(스칼라)를 곱한 값. 스칼라는 방향 없이 크기만을 가진 값을 뜻하며, 벡터와 곱할 경우 크기에 영향을 준다. 벡터의 내적(Dot Product) : 벡터와 벡터를 곱했을 때, 스칼라값으로 변하는 곱. A · B 꼴 로 표현한다. : A = (a1,a2,a3), B = (b1,b2,b3)일 때, A · B = ( a1*b1 , a2*b2 , a3*b3 ) 로 계산된다. 벡터의 외적(Cross Product) : 벡터와 벡터를 곱했을 때, 벡터값을 유지하는 곱. A×B 꼴로 표현한다. : A = (a1,a2,a...

220608) Tree의 전위순회, 중위순회, 후위순회

이미지
Tree형 자료구조에는 노드가 가지처럼 뻗어있으며, 이들을 방문하는 방식이 여러가지가 있다. 최상위의 노드를 '루트'라고 부르고, 그 밑으로 뻗어 나있는 것들을 '서브트리'라고 한다. 또한 자신을 부모노드라고 칭할때, 그 밑으로 노드를 가졌다면 그 노드를 자식노드라고 부른다.  마지막으로, 자식노드가 없는 가장 마지막으로 뻗은 노드를 '리프'라고 부른다 ----- 전위순회 : 루트 노드를 시작으로 왼쪽->오른쪽순으로 서브트리를 방문하는 방식 ----- 중위순회  : 왼쪽 서브트리 -> 부모노드 -> 오른쪽 서브트리 순으로 방문하는 방식 ----- 후위순회 : 왼쪽 서브트리 -> 오른쪽 서브트리 -> 부모노드 순으로 방문하는 방식

220607) Lvalue, Rvalue, 복사생성자, 이동생성자, Rvalue Reference

이미지
Lvalue  : 메모리 주소를 포함하고 있는 값, 일반적으로 변수에 저장되어 표현식 계산 후에도 값을 유지한다. Rvalue  : 표현식 이후에는 사용되지 않는 일시적인 값, 일반적으로 계산이 종료되면 소멸한다. 복사생성자  : 기존 클래스의 데이터를 복사해서 생성하는 생성자.  : 깊은 복사(Deep Copy)를 통해 복사대상의 포인터 멤버변수 참조값마저도 복사해서 새 포인터에 붙여 넣는다는 특징이 있다.  : STL Vector의 push_back()이 복사생성자의 원리를 활용한다.  : Func(const Func& func) 꼴로 사용한다. 이동생성자  : 클래스의 데이터를 가져와서 생성하는 생성자. 복사생성자와 언뜻 비슷해 보이지만 매개변수 클래스가 가진 포인터 멤버변수의 참조소유권을 대상에게 넘긴다는 차이가 있다. 이동 후의 매개변수 클래스가 가지고 있던 포인터 멤버변수의 참조는 해제된다.  : 얕은 복사(Shallow copy)를 사용하기 때문에 메모리 부담이 적다.  : STL Vector의 emplace_back()이 이동생성자의 원리를 활용한다.  : Func(Func&& func) 꼴로 사용한다. Rvalue Reference  : 임시적인 값인 Rvalue값을 참조할 수 있게 하는 방법. Lvalue참조에 비해 리소스 이동에 따른 데이터 변질이 일어나지 않는다.  : 자료값 뒤에 &&를 붙여 표현한다. ( 예: int&& a; ) 또한 이동생성자의 매개변수로서 사용되기도 한다.  : 아래와 같이 Lvalue참조가 Lvalue만을 받을 수 있는 것처럼, Rvalue또한 Rvalue만을 받을 수 있다.

220603) 캐시 메모리, 바이트 패딩

캐시 메모리  : CPU가 필요한 데이터가 있을 때 가장 먼저 접근할 수 있는 캐시 메모리에서 찾는다. 캐시 메모리에서 원하는 정보를 얻으면 Cache Hit 라 부른다. Cache Hit 빈도가 높을수록 정보처리 성능이 높아진다.  : 캐시 메모리에서 원하는 데이터를 찾지 못하면  Cache Miss 라고 하여 이 경우 메모리 저장소에서 찾아 캐시 메모리에 업로드한다. 바이트 패딩  : 클래스/구조체에 바이트를 부여해 CPU의 부하를 덜어주는 기법이다. 부여되는 바이트는 현재 구조체/클래스가 가지는 용량(padding)이며 특정 분량만큼 확보한다. 이는 용량 낭비로 비쳐 보일 수 있으나, 한 번에 정해진 한 움큼 단위의 바이트를 확보함으로써 메모리-CPU 간의 이동 횟수를 줄이고 Cache Hit 비율을 높이기 위한 방법이기도 하다.

220602) cpu, 랜덤 엑세스, 메모리 구조, 배열, 연결리스트

이미지
 CPU  - 중앙 처리 장치(中央處理裝置) 또는 CPU(영어: central processing unit, central/main processor)는 컴퓨터 시스템을 통제하고 프로그램의 연산을 실행 · 처리하는 가장 핵심적인 컴퓨터의 제어 장치이다. CPU 중에서도 각종 전자부품과 반도체 칩을 하나의 작은 칩에 내장한 형태를 마이크로프로세서라고 한다. 액세스  - 순차접근(Sequential access): 첫 번째 값부터 원하는 값이 있는 위치까지 차례대로 접근하는 방식  - 임의접근(Random access): 정해진 주솟값을 통해 바로 접근하는 방식 메모리 구조  : 계층구조로는 레지스터, 캐시, 메모리, 하드디스크 등으로 나뉜다.  : 또는 메모리 내부에서는 코드 영역, 데이터 영역, 힙 영역, 스택 영역으로 나뉜다. 배열  : 같은 타입의 데이터를 여러 개로 나열한 자료구조, 배열 한 칸당 하나의 인덱스를 배정 받으며, 인덱스 번호를 통한 데이터 접근(임의 접근)이 가능하기 때문에 접근속도가 빠르지만, 칸 사이에 데이터를 삽입/제거하기 번거로운 단점이 있다. 링크드 리스트  : 첫 번째 인덱스부터 차례대로 접근하는 방법(순차 접근)을 사용하는 자료구조, 배열에 비해 검색이 느리다는 단점이 있지만 각 데이터를 잇는 포인터가 가리키는 주소의 수정이 용이하기 때문에 삽입/제거가 빠르다.

테스트

 테스트