증감 연산자
++과 -- 가 있다.
전위 연산자
후위 연산자
int a = 0;
//전위
++a;
//후위
a++;
전위와 후위의 오버로딩은 다음과 같이 이루어진다.
증가 및 감소 연산자 오버로드(C++)
자세한 정보: 증가 및 감소 연산자 오버로드(C++)
learn.microsoft.com
주의해야 할 사항은 후위 형식에 대한 연산자를 오버로드 할때는 추가인수로 int만 넣어줘야 한다는 것이다.
class MyInt
{
public:
MyInt()
:m_Int(0) {};
MyInt(int _Value)
:m_Int(_Value) {}
MyInt& operator++()
{
m_Int += 1;
return *this;
}
MyInt operator++(int)
{
MyInt temp = *this;
++*this;
return temp;
}
friend ostream& operator<<(ostream& os, const MyInt& myInt)
{
os << myInt.m_Int;
return os;
}
private:
int m_Int;
};
MSDN에서 보여주는 증감연산자 오버로딩 방식을 보면
아마도 전위 연산자와 후위 연산자의 동작이 이런식으로 이루어진다고 추측해볼 수 있다.
마이크로소프트 공식문서니까 대충 맞을 것이다.
이 코드를 기준으로 전위 후위 증감연산자를 사용한 결과를 출력해보자.
int main()
{
MyInt n(10);
cout << n++ << '\n'; // return temp = 10(n = 11)
cout << ++n; // return n(n = 12)
return 0;
}
MyInt n을 10으로 초기화 했고
n++는 10에서 +1을 한 결과가 나올 줄 알았는데 10을 출력하고 있다.
후위 증감 연산자 오버로딩한 코드를 보자.
temp라는 임시 객체를 만들어서 그 객체에 this( = n)의 값만을 집어넣고 있다.
그후에 this의 값에 대해서 +1을 해주고 리턴은 temp만 해주는 것을 볼 수 있다
이러면 n++는 return은 n에 +1을 하기 전인 temp의 값이 리턴되고
n의 값은 1이 증가하는 결과를 가지게 되어
결과적으로 출력은 변경되기 이전의 값인 temp의 10을 출력하게 된다.
그다음 cout << ++n을 보면 12를 출력하고 있다.
왜냐하면 앞의 n++에 의해서 출력만 10을 출력했지 n자체는 증감연산자로 11이 된 상태이다.
전위 증감 연산자는 위에는 this가 생략되었지만 사실상
this->m_Int += 1를 하고
return *this를 하기 때문에 변경된 n의 값인 12를 출력하는 것을 알 수 있다.
위의 차이 외에도
후위 증감 연산자는 전위 증감 연산자와 비교했을때 temp라는 임시 객체를 생성하기 때문에
최적화 단계서 전위 연산자가 유리한 측면이 있을 수 있다.
그러나 최근 컴파일러는 이런 부분에 대해 알아서 최적화를 해주기 때문에 큰 차이는 없다고 함.
Release와 Debug
디버그로 정상적으로 빌드가 되는데 릴리즈로는 안되는 상황이 있을 수 있음.
릴리즈로 실행했을 때 안되면 평가 0점.
그러므로 포트폴리오 제작 시작했을 때 점심먹기 전, 강의실 퇴실 전 릴리즈로 한번씩
하루 2번 빌드해볼 것.
그러므로 따로 특별한 게없으면 프로젝트를 설정할 일이 있을때 가급적 모든 구성을 통해 설정하도록 하자
x86, x64
32비트, 64비트를 뜻한다. 요새 x86을 쓰는곳은 없다고 봐도 무방.
static (정적변수)
1. 전역변수 static
전역변수를 어떤 헤더에 구현해놓고 a.cpp b.cpp에서 include하는 경우
a와 b 모두 같은 이름의 변수를 정의하게 되기 때문에 오류가 발생한다.
그런데 static을 붙이면 오류가 발생하지 않는다.
변수를 cpp마다 만들어주기 때문에 => extern과는 다르다.
그러나 객체지향에서 전역 static은 딱히 쓸 필요가 없다.
2. 클래스 static
- 클래스의 모든 인스턴스가 동일한 변수를 공유
- 인스턴스가 없어도 클래스 이름을 통해 직접 접근가능
- 객체마다 별도의 값을 갖는 것이 아니라 단 하나의 값으로 유지
- 클래스 내부에서 선언하고 클래스 외부에서 정의해야 사용할 수 있음.
함수 호출 규약
함수가 호출될 때 함수 매개변수의 전달 방식과 스택을 관리하는 방식을 정의하는 규칙
함수가 매개변수를 스택에 어떻게 푸시하고 함수 호출 후 스택을 누가 정리하는지에 대한 차이를 설명하는것.
__cdecl(c 선언 방식)
c++에서 기본적으로 사용되는 호출 규약.
가장 많이 사용되며 c/c++라이브러리 함수들이 사용하는 방식
- 매개변수는 오른쪽에서 왼쪽순서로 스택에 push
- 호출자가 스택을 정리함. 함수가 반환된 후 스택 포인터를 복구하는 작업을 호출자가 수행.
이로 인한 오버헤드가 발생할 수 있음.
- 가변인자를 지원한다. printf()와 같은 함수에서 인자의 개수가 고정되어 있지 않은 함수에서도 사용된다.
__stdcall(표준 호출 방식)
윈도우 API함수에서 많이 사용되는 호출 규약. 주로 함수 라이브러리나 시스템 콜에 사용
- 매개변수는 오른쪽에서 왼쪽순서로 스택에 push
- 피호출자가 스택을 정리함. 함수가 끝날 때 스택포인터를 복구하는 작업을 수행. 오버헤드 감소
- 가변인자 사용불가.
__thiscall(멤버 함수 호출 방식)
c++ 클래스의 멤버 함수에서 기본적으로 사용되는 호출 규약
- this 포인터 : this 포인터는 첫 번째 매개변수로 전달됨
- 나머지 매개변수는 오른쪽에서 왼쪽순서로 스택에 push
- 비가상 멤버함수에서는 피호출자가 스택을 정리한다. 가상함수 호출의 경우 호출 규약이 달라질 수 있다.
그러나 현 수준에서 신경 쓸 필요 없는 단계임
기본적으로 Visual Studio에서
__cdecl로 알아서 처리해준다
열거형
사용자 정의자료형 중의 하나.
class, struct, enum, union
enum은 정수형 상수를 정의하는 문법.
어떠한 의미를 숫자로 바꾸는 것
사용자 정의자료형 중의 하나.
class, struct, enum, union
enum은 정수형 상수를 정의하는 문법.
어떠한 의미를 숫자로 바꾸는 것.
enum과 enum class 존재
enum
이름이 없는 상수들의 그룹을 정의한다. 정수형으로 처리되고 다른 정수형 값과 암묵적으로 변환이 가능하다.
- 전역 네임 스페이스에 포함
- 암시적으로 정수형 변환이 된다.
- enum끼리 값 충돌 가능성이 있다.
- 타입의 안정성이 낮음
enum Color { Red, Green, Blue };
int main() {
Color c = Red;
int n = c; // enum 값이 암시적으로 int로 변환됨
if (n == 0) {
cout << "Red is 0" << endl;
}
}
enum class
전통적인 enum의 문제점을 보완하기 위해 나온 새로운 열거형 방식, 네임스페이스 충돌 문제와 암시적 형변환 문제 해결
- 열거형 상수가 열거형 스코프 내에서만 유효 (예) MyEnum:: 이런식으로 명시해줘야 쓸 수 있음
- 암시적 형 변환을 허용하지 않는다.
- 동일한 이름을 가진 열거형 상수를 다른 열거형 내에서 정의 가능(스코프가 다르기 때문에)
- 타입의 안정성이 높다.
enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };
int main() {
Color c = Color::Red;
// int n = c; // Error: 암시적 변환이 허용되지 않음
if (c == Color::Red) {
cout << "Color is Red" << endl;
}
TrafficLight light = TrafficLight::Red;
// if (c == light) { // Error: 다른 enum class끼리 비교 불가
}
'개인 공부 및 프로젝트 > 국비과정' 카테고리의 다른 글
20241011 - default parameter, list initializer (0) | 2024.10.24 |
---|---|
20241010 - 추상클래스, 동적 할당 (0) | 2024.10.24 |
20241007 - 자료구조 (0) | 2024.10.24 |
20241004 - 소멸자, 함수포인터, virtual (0) | 2024.10.18 |
20240930 - 선언과 구현, 파일 입출력 (3) | 2024.10.07 |