목록c++ (29)
게임 개발 메모장
경쟁 상태 : 여러 스레드가 공유 리소스를 동시에 접근. : x86 프로세서에서 제공하는 INC는 아토믹하지 않으므로, 두 스레드의 작업이 겹치게 되면 예상치 못한 결과를 얻을 수 있다. 테어링 * 읽기 테어링 : 1번 스레드가 메모리에 데이터의 일부분만 쓰고 나머지 부분을 다 쓰지 못한 상태에서 2번 스레드가 이 데이터를 읽으면 두 개의 스레드가 보는 값이 달라진다. * 쓰기 테어링 : 두 스레드가 동일한 데이터의 다른 부분을 각각 쓰는 경우 각자 수행한 결과가 달라진다. 데드락(교착 상태) : 경쟁 상태를 막기 위해 상호 배제와 같은 기법을 사용할 때 발생하는 문제. 예시 : 1번 스레드는 A를 확보하고 B를 추가적으로 필요로 하는 동시에 2번 스레드는 B를 확보하고 A를 추가적으로 필요로 하는 상황..
이동 생성자란? 이름 없는 임시 객체가 생기는 것을 막을 수 없다. 그러나 무의미한 임시 객체의 생성은 프로그램의 효율을 떨어뜨린다. 이러한 문제 때문에 생긴 것이 이동 생성자이다. 임시 객체는 어차피 사라지는 객체이다. 깊은 복사를 수행할 필요 없이 얕은 복사를 수행함으로써 성능을 높일 수 있다. #include using namespace std; class TestClass { public: TestClass() { cout
복사 생성자(copy constructor)란? 복사 생성자란 객체의 복사본을 생성할 때 호출되는 생성자이다. 복사 생성자도 생성자와 마찬가지로 정의하지 않으면 컴파일러가 자동으로 만들어준다. 복사 생성자의 형태는 다음과 같다. 클래스이름(const 클래스이름 &변수이름); 다음 예제는 복사 생성자를 사용하였고 생성자와 마찬가지로 멤버 변수를 초기화하였다. #include using namespace std; class TestClass { public: TestClass(int param) : num(param)//생성자 초기화 { cout
main 안에서 실수로 값을 초기화 해버리는 문제가 생길 수 있는데, 이를 막을 수 있는 방법이 있을까? 정적 멤버 데이터(static member data) - static이 붙은 멤버 데이터 - 모든 객체가 공유한다. - 클래스 내부에 선언을 만들고 클래스 외부에 정의를 만들어야 한다. - 모든 객체가 공유한다. - 멤버 이므로 접근 지정자를 사용할 수 있다. class 내부에 static으로 변수를 선언한다. private로 선언하면 class 내부에서 getter/setter를 통해 해당 변수에 접근이 가능하게 만들 수 있다. class 내부에 static으로 선언된 cnt 값을 c1.getCount()로 호출해 가져올 수 있다. 출력 : 3 정적 멤버 데이터와 일반 멤버 데이터 아래 코드에서 -..
C++에선 런타임에 기초 클래스의 객체 포인터가 어떤 객체를 가리키고 있는지 정보를 알려주는 RTTI 기능을 제공한다. 객체지향에선 클래스 간 상속을 구현할 수 있고, 다형성을 가지게 되어 기초 클래스(Base class)는 자신의 멤버를 위임한 파생 클래스(Derived class)를 자신의 객체 포인터로 가리킬 수 있다. Base *pBase = new Derived(); 하지만 컴파일 당시에는 pBase가 어떤 객체를 가리키고 있는지 알 수 없다. 그저 가상 함수 테이블 vftable에 저장된 함수 주소가 무엇인지에 따라서만 기초 클래스와 파생 클래스 중 어떤 객체를 가리키고 있는지 짐작할 수만 있다. 하지만 그 자체가 정보로 주어지는 것도 아니기 때문에 프로그램은 실행 중에 포인터가 가리키고 있는..
복합 대입 연산자와 마찬가지로 복합 대입 연산도 가능하도록 할 수 있다. #include using namespace std; class TestClass { public: TestClass() {} ~TestClass() {} //변환 생성자 TestClass(int param) { num = new int; *num = param; } //형변환 허용 operator int() { return *num; } //복합 대입 연산자 TestClass& operator+=(const TestClass& ref) { //현재 값 int* newNum = new int(*num); //누적 값 *newNum += *ref.num; //기존 값 지우고 새 메모리 대체 delete num; num = newNum..
변수뿐만 아니라 클래스나 구조체에서도 단순 대입 연산이 이루어질 수 있다. #include using namespace std; class TestClass { public: TestClass() {} TestClass(int param) { num = new int; *num = param; } TestClass(const TestClass& ref) { num = new int; *num = *ref.num; } ~TestClass() { delete num; } int getNum() { return *num; } private: int *num = nullptr; }; int main() { TestClass a(10); TestClass b(20); a = b;//에러 cout
C++ const, constexpr constexpr 이란 컴파일 시간 상수를 만드는 키워드 컴파일 시간에 결정되는 상수 값으로만 초기화 할 수 있다. constexpr이 변수를 상수로 만들어 준다고 하는데 그럼 const와 똑같은데 무슨 차이가 있나? 상수에는 2가지 상수가 존재하는데 1. 컴파일 시간에 알 수 있는 상수. 2. 컴파일 시간에 알 수 없는 상수. (실행시간에 알 수 있는 실행시간 상수) 이렇게 두 종류의 상수가 존재한다. 컴파일 시간에 알 수 있는 상수를 컴파일 시간 상수 (compile-time constant)라고 하고, 컴파일 시간에 알 수 없는 상수 즉 실행시간에 알 수 있는 상수를 런타임 상수(runtime constant)라고 한다. const는 컴파일 시간에 알 수 있는 ..
동기식 (Synchronous) 작업을 하나 시작하고 완료되면 다음 작업을 시작한다. 예를 들어, 서버에 요청을 보낸 뒤에 클라이언트에서 결과를 받아야 다음 작업을 시작하는 방식 비동기식 (Asynchronous) 서버에 요청을 보낸 뒤에 동기 방식과 달리 바로 다음 작업을 시작한다. 동기 방식에 비해서 자원을 효과적으로 처리할 수 있다. 따라서, 동기 방식과 달리 작업이 끝나면 이를 알 수 있도록 처리 결과를 반환하는 콜백 함수가 필요하다.
C언어에는 lvalue(left value), rvalue(right value) 라는 개념이 존재한다. 이 왼쪽 값, 오른쪽 값이란 단어의 의미는 매우 직관적으로 등호 (=) 의 왼쪽에 있으면 lvalue , 오른쪽에 있으면 rvalue 이다. 대입받는 값, 대입되는 값이라고도 할 수 있다. lvalue 표현식 이후에도 사라지지 않는 값. 이름을 지니는 변수. rvalue 표현식 이후에는 사라지는 값. 임시 변수. 굵은 밑줄이 쳐진 것이 rvalue 이다. x+y 따위는 실제 변수가 아니라 임시 변수를 생성하여 (레지스터인지 메모리인지)에 저장, 사용한다. 이 값은 일반 변수와 마찬가지로 int 등의 타입을 가지고 있지만 계산이 끝나면 사라지는데 이것이 rvalue 이다. 그리고 명시적으로 선언하여 '..