[C++] boolean
REF : 윤성우의 열혈 C++
새로운 자료형 bool
C의 최근 표준에서는 bool을 기본 자료형으로 추가했지만,
상당수의 컴파일러는 여전히 bool을 지원하지 않는다.
참과 거짓을 의미하는 true, false
C, C++ 모두 정수 0은 false, 나머지 모든 정수는 true로 인식한다. 그래서 보통
#define TRUE 1
#define FALSE 0
이렇게 정의하고 사용한다.
C++에는 위 키워드를 기본적으로 지정하고있기에 따로 define을 해줄 필요가 없다.
C++에서 true와 false를 사용하면 기본적으로 1과 0으로 표현되며,
이 둘 모두 1바이트만큼의 공간을 차지하는 자료형이된다.
그래서 출력하면 각각 0과 1로 출력되고,
굳이 정수로 사용하겠다면 0과 1로 사용할 수 있다.(추천되지 않음)
독립적인 자료형이라고 생각해야한다.
자료형 bool
true와 false는 자체로 참과 거짓인 데이터이므로, 자료형이 따로 지정되어있다.
이들을 bool형 데이터라고 부르는데, 기본 자료형 중 하나이므로 선언이 가능하다.
bool isTrue=true;
bool isFalse=false;
이렇게 선언할 수 있다.
참조자의 이해
할당된 하나의 메모리 공간에 둘 이상의 이름을 부여하는 방법
int num1 = 2022;
이렇게 num1이라는 변수를 선언하면,
2022로 값이 초기화된 4바이트짜리 메모리공간에 num1이라는 이름이 붙는다.
그런데, 여기서 밑의 문장을 실행하면 이름을 하나 더 붙일 수 있다.
int &num2=num1;
num2라는 이름으로 num1에도 접근할 수 있다.
&연산자는 변수의 주소값을 반환하는 연산자이지만, 새로운 변수를 선언할 때 사용하면
참조자의 선언
을 의미한다.
변수의 주소값을 반환할 때의 쓰임새는 보통
int *ptr = &num1;
이렇게 쓰이지만, 참조자로 쓰기 위해선
int &num2=num1;
num2를 num1의 참조자로 선언할 수 있고,
num2 = 2023;
cout<<num1<<endl;
cout<<num2<<endl;
$>2023
$>2023
참조자num2에 대한 연산은 num1에도 적용된다는 것을 알 수 있다.
C에서 위와같이 사용하기위해서는, 포인터를 선언해 num1을 가리키게하고,
내부 값을 바꿀 때마다 *
역참조를 계속 해주어야하지만, C++에선 참조자를 선언해 이를 생략할 수 있다.
참조자는 별칭이다
전통적으로 C++에서는 참조자를
변수에 별칭을 하나 붙여주는 것입니다.
라고한다.
참조자 수에 제한이 없고, 참조자를 대상으로 참조자를 선언할 수 있다.
하나의 변수에 대해 참조자를 여러개 선언할 수 있다.
int num1=24;
int &num2=num1;
int &num3=num1;
int &num4=num1;
int &num5=num1;
또한, 참조자를 대상으로 참조자를 선언할 수 있다.
int num1=24;
int &num2=num1;
int &num3=num2;
int &num4=num2;
int &num5=num2;
참조자의 선언 가능 범위
참조자는 변수에 대해서만 사용가능하다.
선언됨과 동시에 변수를 참조해야하므로, 이미 선언된 변수에만 사용할 수 있따.
또한, 선언하면서 NULL로 초기화하는 것은 불가능하다.
int &ref=20 (x)
int &ref; (x)
int &ref=NULL (x)
단, 포인터도 변수이므로, 포인터에는 참조자 선언이 가능하다.
int num = 12;
int *ptr=#
int **ptr2=&ptr;
int *(&ref)=ptr;
int **(&ref2)=ptr2;
참조자와 함수
참조자의 활용에는 함수가 큰 위치를 차지한다.
Call-by-value와 Call-by_reference
C언어에서 함수를 호출할 때, 2가지 방식이 있었다.
Call-by-value는 값만을 전달한다.
int Addr(int num1, int num2)
{
return (num1 + num2);
}
이렇게 Call-by-value함수의 특징은 함수의 인자로 전달되는 변수가
값
만이 전달되어서
함수 내부에서
int num1 = 인자1;
int num2 = 인자2;
이렇게 선언되는 것과 다를 바 없다.
이때, 함수 내부에서는 함수 외부의 값에 영향을 줄 수 없는데,
함수 외부의 값에 영향을 주기 위해선 Call-by-reference
기반의 함수이다.
void SwapByRef(int *ptr1, int *ptr2)
{
int temp=*ptr1;
*ptr1 = *ptr2;
*ptr1=temp;
}
함수 외부의 변수의 주소값을 전달함으로써,
함수 내부에서 함수 외부의 값에 직접 접근할 수 있다.
C++에서는 주소값으로 접근할수도 있지만,
참조자를 통해서 접근할수도 있다.
참조자를 이용한 Call-by-reference
C++에서 참조자를 기반한 Call-by-reference의 함수를 만들때는 매개변수의 인자로 참조자를 선언하면된다.
void SwapByRef(int &ref1, int &ref2)
{
int temp=ref1;
ref1=ref2;
ref2=temp;
}
함수의 인자로 변수가 주어지면, 함수에서는 내부적으로
int &ref1=인자1;
int &ref2=인자2;
이렇게 선언과 동시에 초기화되면서 참조자를 사용할 수 있다.
참조자가 복잡하게 역참조해야하는 연산을 줄여준다는 것을 생각할 때,
C언어와 비교해 진짜 편한 기능임을 알 수 있다.
참조자를 이용한 Call-by-reference의 황당함과 const참조자
참조자 기반의 함수정의의 문제점은
함수의 호출문장만 보고도 함수의 특성을 파악할 수 없다는 것이다.
기존에 C언어에서는 매개변수로 전달되는 인자만 보고도 확인할 수 있었지만,
C++에선 참조자가 매개변수로 온다면
함수의 몸체까지 문장단위로 확인해 참조자를 통한 값의 변경이 있는지 확인해야한다.
이를 위해, C++에선 const
키워드로 함수의 원형만 보고 확인할 수 있다.
void NotChangeV(const int *ref);
이 함수의 원형을 보면, const가 int *ref 앞에 옴으로써,
가리키는 값을 상수로 만들어 값을 변경할 수 없음을 알 수 있다.
반환값이 참조형인경우
함수의 반환형에 참조형이 선언될 수 있다.
int& RefRetFunctOne(int &ref)
{
ref++;
return (ref);
}
매개변수로 참조자가 선언되었는데, 이 참조자를 그대로 반환한다.
ref++을 하면 참조자가 1더해지고, 더해진 이 참조자를 반환하게된다.
단, 참조자를 매개변수도 받더라도, 일반 자료형을 반환할수도 있다.
int RefRetFunctTwo(int &ref)
{
ref++;
return (ref);
}
이때, 참조자는 1 더해졌지만, 반환하는 자료형은 일반 자료형이라서
이 함수가 반환하는 값으로는 더이상 참조자에 접근할 수 없다.
잘못된 참조의 반환
int& RetuRefFunc(int n)
{
int num = 20;
num+=n;
return num;
}
위 함수의 문제점은 함수 내부의 지역함수를 참조자로 반환하고 있다는 것이다.
만약 함수를 사용할 때
int &ref=RetuRefFunc(10);
이런식으로 사용하게되면 ref라는 참조자에 함수내부의 지역변수 num이 할당된다.
하지만 num은 지역변수
이므로, 함수가 종료되면 스택메모리에서 빠져나가면서 소멸된다.
컴파일러는 이에 대해 에러메세지가 아닌, 경고메세지만 띄워주고,
찌꺼기의 쓰레기값을 참조하기때문에 주의해야한다.
const 참조자의 또 다른 특징
- 상수화된 변수에 대한 참조
const int num=20;
int &ref=num;
ref+=10;
cout<<num<<endl;
const 선언으로 num을 상수화한다.
상수화된 변수에 참조자 ref를 선언한다.
그리고 참조자에 대한 변경을 시도한다.
위 코드는 C++의 컴파일러가 문제를 일으킨다.
상수화된 변수에 대한 일반적인 참조자의 선언은 컴파일에러를 일으킨다.
만약, 상수화된 변수에 대해 참조자를 선언하기 위해선, 참조자에게도 const키워드를 넘겨주면된다.
const int num2-;
const int &ref=num;
- 상수에 대한 참조
const 참조자는 상수도 참조할 수 있다.
const int &ref=50;
일반적인 상수는 리터럴 상수로, 해당 행에만 임시적으로 존재한다.
참조자가 상수를 참조할 수 있는 이유는, C++에서 상수를 참조할 때, 임시변수
를 만들기 때문.
메모리에 해당 상수에 대한 공간을 만들어서 변수처럼 사용할 수 있다.
이런 임시변수를 생성해 상수를 참조하는 방법도 결과적으로는 1의상수화된 변수를 참조
하는 것과 같은게 된다.
댓글남기기