검색결과 리스트
프로그래밍/C++ 에 해당되는 글 55건
- 2024.12.06 기억 존속 시간
- 2022.07.27 C#에서 Form이 키보드 안 먹을 때
- 2022.05.20 unique_ptr 대입 방법
- 2021.08.18 0xC0000005 오류
- 2021.01.19 ERROR C7525 인라인 변수에는 '/std:c++17' 이상이 필요합니다
- 2021.01.19 Visual Studio에서 탭 공백 삽입
- 2020.11.20 리팩토링 원칙
- 2020.11.19 C++ 11 항목
- 2020.11.19 인다이렉션
- 2020.11.19 리팩토링을 해야 할 때
- 2020.11.19 리팩토링의 정의
- 2020.09.18 C++11 배열 초기화
- 2020.09.18 C++11에서의 auto 선언
- 2020.07.27 게임 루프와 게임 클래스
- 2019.09.18 fatal error C1189
헤더 파일 내용
1. 함수 원형
2. 기호 상수, #define, const
3. 구조체 선언
4. 클래스 선언
5. 템플릿 선언
6. 인라인 함수
기억 존속 시간(Storage duration)
1. 자동 - 자동변수 - 지역변수, 블록 (쓰레기 값)
2. 정적 - 정적변수 - 전역변수, static (0)
3. 동적 - 동적변수 - new, delete
4. 쓰레드
사용범위(Scope)
어떤 이름이 하나의 파일 안에서 얼마나 널리 알려지는가?
1. 블록 - 지역
2. 파일 - 전역
링크(Linkage)
서로 다른 번역 단위들이 이름을 공유하는 것
1. 외부링크(external linkage) - 여러 파일들이 이름을 공유
2. 내부링크(internal linkage) - 한 파일 안에 있는 함수들만 공유
3. 링크 없음
this.KeyPreview = true;
이것을 Load 함수에서 호출하면 바로 키보드가 먹는다
이거 때문에 개고생에서 시간을 오래 끌었다
CApple* pApple;
pApple->Show( );
다음과 같은 경우 발생한다
참조되지 않은 포인터, 즉 정확한 메모리 위치를 가리키지 않고 사용할 때 발생한다
또는 다음과 같은 경우도 있다
CApple* pApple = new CApple( );
// pApple 사용
delete pApple;
pApple->Show( );
위와 같은 경우도 마찬가지이다
일반적인 프로그램에서도 먼저 포인터를 삭제한 후
다른 곳에서 갖다 쓸 때 발생하는 에러이다.
CAppleDlg::CAppleDlg( )
{
m_pApple = new CApple( );
}
CAppleDlg::~CAppleDlg( )
{
delete m_pApple;
}
CAppleUse::Process( )
{
CAppleDlg dlg;
m_pApple = dlg.GetApple( );
}
CAppleUse::Select( )
{
m_pApple->Show( ); // 0xC0000005 오류 발생, 이미 ~CAppleDlg( )에서 객체 삭제
}
ERROR C7525 인라인 변수에는 '/std:c++17' 이상이 필요합니다
Visual Stuidio 2019를 사용해서 빌드하는데 갑자기 저런 오류가 뜬다
이유는 C++ 언어 표준이 IST C++14 표준으로 되어 있기 때문에다
이런 경우는 ISO C++17 표준으로 설정하던지
미리보기 - 최신 C++ 초안의 기능(/std:c++latest) 로 설정하면 된다
왜 Visual Studio 2019인데 C++17로 설정을 안 했는지
또는 최신으로 설정 안 하고 IST C++14로 설정했는지는 모르겠다
변수를 사용하는 부분에 있어서 가능하면 const를 사용하라
int i = 10;
for(int j = 0; j < i; ++j)
{
++i;
}
무한 루프로 돌아 논리 상의 버그이다
하지만 const int i = 10; 으로 선언하면 코드 오류이기 때문에 컴파일러가
잡아낸다
따라서 가능한 많은 경우에 const를 사용하자
explicit Annotation(const string text)
: value(move(text))
{
}
위의 코드는 에러가 난다
value에 text를 넣는데 text를 넣고 move를 하면 text에는 nullptr이 들어가는데
const로 되어 있기 때문에 변경이 안 된다
위와 같은 경우는 const를 삭제해야 한다
template <typename T>
void swap(T& a, T& b) {
T tmp(a);
a = b;
b = tmp;
}
위의 코드보다는 아래의 코드가 훨씬 효율적이다
template <typename T>
void swap(T& a, T& b) {
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
auto
변수의 자료형을 컴파일 시간에 자동으로 추론
선언시 추론된 형은 종료시까지 사용됨
대입시 자료현 변경이 안 됨
auto a = 10; // int
auto b = 1.0f; // float
auto c = 1.0; // double
auto d = "abc"; // char*
auto e = {1, 2, 3}; // std::initializer_list
auto f = { 10 }; // c++ 14까지는 std::initializer_list, c++17 부터는 int
auto g { 10 }; // int
g = 12.34; // warning C4244: '=' 데이터 손실
string h = { "abc" };
auto i = h.begin( ); // std::string::iterator
vector<int> v = {1,2,3,4,5};
//auto 키워드를 사용한 전 vector를 순회하는 반복자의 선언
for (intVector::iterator it = v.begin(); it != v.end(); ++it) {
cout << *it << endl;
}
//auto 키워드를 사용한 후 vector를 순회하는 반복자 선언
for (auto it = v.begin(); it != v.end(); ++it) {
cout << *it << endl;
}
//auto 키워드를 이용한 for loop
for (auto& value : v) {
cout << value << endl;
}
value category ( 값 유형 )
값의 분류 기준
값이 식별성을 갖고 있는가?
값이 메모리에서 이동할 수 있는가?
(gl-value, pr-value, x-value, l-value, r-value)
값 유형 값이 메모리에서 이동 값이 메모리에서 이동 X
값이 식별성을 가질 때 x - value l - value gl-value
값이 식별성이 없을 때 pr-value
(임시 변수)
r-value
int && c = 10;
r-value를 참조하는 연산자
decltype
현재 변수나 표현식의 타입을 알아낼 수 있는 명령어
int a = 10;
decltype(a) b = 2; // int b = 2;
int& x = a;
decltype(x) c = b; // int& c = b;
const int i = 4;
auto j = i; // int j = i;
decltype(i) k = i; // const int k = i;
int arr1[10];
auto arr2 = arr1; // int* arr2 = arr1;
decltype(arr1) arr3 = arr1; // int arr3[10] 으로 선언
decltype 키워드
템플릿 함수에서 어떤 객체의 타입이 템플릿 인자들에 의해서 결정되는 경우
template <typename T, typename U>
void add(T t, U u, decltype(t + u)* result) {
*result = t + u;
}
template <typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
vector의 emplace_back( )과 push_back( )의 차이
push_back( ) 메서드
- 일반적으로 '객체' 삽입
- 객체가 없이 삽입하려면 임시 객체(rvalue) 가 있어야 함
- 암시적 형 변환이 가능하다면 인자로도 삽입
- 이는 인자를 통해 임시객체를 암시적으로 생성한 후 삽입
std::vector<myString> vecString;
myString str = "hello1";
vecString.push_back(str); // str 객체 소멸
vecString.push_back(myString("hello2")); // 임시 객체 소멸
vecString.push_back("hello3"); // 임시 객체 소멸
vecString.push_back(std::move(myString("hello4")); // 해제 안 됨
대입에 관한 이동 연산자
myString& operator=(myString&& right);
인다이렉션의 정의
- 어떤 기능을 수행하는 코드가 직접 들어 있는 것이 아니라 기능 별로 분리되어 있는 다른 메서드를 참조하는 방식
- 값 자체가 아니라 이름, 참조, 컨테이너 등을 사용해서 대상을 참조
- C 언어의 포인터, C++ 템플릿
인다이렉션의 장점
- 로직의 공유 : 두 위치에서 호출되는 하위 메서드나 모든 하위 클래스가 공유하는 상위 클래스의 메서드 등
의도와 구현을 따로 나타냄 :
리팩토링을 할 때의 문제
- 데이터 베이스
- 인터페이스 변경
- 언제 리팩토링을 하지 말아야 하는가?
마감일이 얼마 남지 않았을 때
코드를 처음부터 다시 작성해야 할 때
리팩토링과 디자인
리팩토링은 디자인을 보완
단순한 디자인을 변경하는 것은 비용이 너무 크다
100 가지 중에서 실제 문제가 발생하는 부분은
찾아서 수정 필요
1. 삼진 규칙 (세 번째로 비슷한 것을 할 때)
2. 새로운 기능을 추가할 때
3. 버그를 수정할 때
4. 코드 리뷰를 할 때
5. 깊이 있는 이해라를 위한 리팩토링
- 개발자로서 코드 기반을 더 깊이 이해하면, 보다 효과적으로 자신의 코드를 보충하거나 코드 개선 방법을 제시
품질을 고려하는 사람이면 리팩토링이 버그를 줄이고 개발 속도롤 빠르게 한다고 설득
배열은 이미 리스트 초기화를 사용하고 있으며, C++11에서는 몇 가지가 추가되었다
먼저, 배열을 초기화할 때, = 부호를 사용하지 않아도 된다
double earnings[4] { 1.2e4, 1.6e4, 1.1e4, 1.7e4 }; // C++11에서 문제 없음
두 번째로, 중괄호를 공백하여 모든 배열을 0으로 초기화할 수 있다
unsigned int counts[10] = { }; // 모든 배열값을 0으로 초기화
float balances[1000] { }; // 모든 배열값을 0으로 초기화
세 번째로, 리스트 초기화시에 narrowing을 방지할 수 있다
long plifs[ ] = { 25, 92, 3.0 }; // 허용 안 됨
char slifs[4] = { 'h', 'i', 1122011, '\0' } // 허용 안 됨
char tlifs[4] = { 'h', 'i', 112, '\0' } // 허용
plifs[ ]는 부동 소수점형에서 정수형으로 변환되기 때문에, 초기화가 실패하게 된다
심지어 소수점 아래 값이 0이라고 하더라도 실패한다
slifs[4]는
C++11은 초기화하는 값을 보고 변수형을 추론할 수 있다
초기화 선언 시 데이터형을 쓰지 않고 auto를 사용할 수 있다
auto n = 100; // n은 int
auto x = 1.5; // x는 double
auto y = 1.3e12L; // y는 long double
그러나 자동으로 데이터형을 추론하는 것을 그렇게 단순하게 생각해서는 안 된다
안 좋은 습관을 가질 수 있다
예를 들어 x, y, z가 모두 double 형이고 다음과 같은 코드를 작성하면
auto x = 0.0 ; // 0.0이 double이기 때문에 문제가 없음
double y = 0; // 0이 자동으로 0.0으로 변환되기 때문에 문제가 없음
auto z = 0; // 이런! 0이 int이기 때문에, z가 int가 되어 문제가 생김
0.0 대신 0을 사용할 경우 문제가 발생하지는 않는다
그러나, 자동 형변환의 경우에는 문제가 발생한다
자동으로 변수형을 추론하는 것은 STL(Standard Template Library)을 사용할 때와
같이 복잡한 변수형을 다룰 때 매우 유용하다
예를 들어 C++98에서는 다음과 같이 코드가 작성된다
std::vector<double> scores;
std::vector<double>::iterator pv = scores.begin();
반면, 코드가 C++11에서는 다음과 같이 작성될 수 있다
std::vector<double> scores;
auto pv = scores.begin();
* 프레임의 구조
상위 수준에서 게임은 각 프레임마다 다음 단계를 수행한다
1. 입력을 받는다
2. 게임 세계를 갱신한다
3. 출력을 만든다
입력 처리는 마우스나 키보드, 또는 컨트롤러 같은 여러 디바이스의 입력을 감지한다
게임의 입력은 궁극적으로 게임의 유형이나 게임이 실행되는 플랫폼에 의존한다
게임 세계의 갱신은 게임 세계의 모든 오브젝트를 거치면서 필요에 따라 게임 오브젝트를 갱신한다는 걸 뜻한다
Console 에서 MFC를 사용할 때 다음 헤더 파일을 포함해야 한다
#include <afxext.h>
Console 에서 MFC 함수를 사용하면 다음과 같은 에러가 난다
fatal error C1189: #error: Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]
원인은 다음과 같다
MFC 공유 DLL을 사용하기 위해서는 MD 대신 MT 로 변경한다
구성 속성 - C/C++ - 코드 생성 - 런타임 라이브러리 - 다중 스레드(/MT)
그리고 전처리기 CONSOLE 대신 WIN32 와 _WINDOWS를 추가한다
NDEBUG;WIN32;_WINDOWS;%(PreprocessorDefinitions)