새로운 자료형 bool
c++에서 true와 false는 참,거짓 의미하는 1바이트 data
#include <iostream>
using namespace std;
int main(void)
{
int num = 10;
int i = 0;
cout << "true: " << true << endl; // true는 참을 의미하는 1바이트 data지만 정수로 변환되어 1 출력
cout << "false: " << false << endl; // 정수로 변환되어 0 출력
while (true)
{
cout << i++ << ' ';
if (i>num)
break;
}
cout << endl;
cout << "sizeof 1: " << sizeof(1) << endl; // 정수 1, 0과는 다름 개념임을 보여줌
cout << "sizeof 0: " << sizeof(0) << endl;
cout << "sizeof true: " << sizeof(true) << endl; // true와 false는 참,거짓 의미하는 1바이트 data
cout << "sizeof false: " << sizeof(false) << endl;
return 0;
}
|
true: true
false: false
0 1 2 3 4 5 6 7 8 9 10
sizeof 1: 4
sizeof 0: 4
sizeof true: 1
sizeof false: 1 |
true와 false는 bool type data
bool type 변수는 true와 false정보를 저장 가능
#include <iostream>
using namespace std;
int main()
{
int num;
bool height;
cout << "당신의 키 입력(cm) : ";
cin >> num;
if (num > 180) height = true;
else height = false;
cout << boolalpha; // bool 변수의 값을 1과 0 대신에 true와 false로 출력하도록 함
cout << "키가 180이 넘는가? " << height << endl;
return 0;
} |
Output :
당신의 키 입력(cm) : 175
키가 180이 넘는가? false
Reference (참조자)
변수는 할당된 메모리 공간에 붙여진 이름이며, 그 이름을 통해 해당 메모리 공간에 접근이 가능
int num1=2010;
위의 변수 선언으로 2010으로 초기화된 메모리 공간에 num1이라는 이름이 붙게 됨
int &num2=num1;
위에서 num2앞에 붙은 &연산자는 참조자의 선언을 뜻하며, 변수 num1에 대한 참조자 num2를 선언해라는 의미.
이 결과, num1이라는 이름이 붙은 메모리 공간에 num2이라는 이름이 더 하나 붙게 됨
num2=3047;
위 문장으로 인해 num1, num2라는 이름이 붙은 메모리 공간에 3047이 저장됨
- 관련 예제
#include <iostream>
using namespace std;
int main()
{
int num = 10;
int &ref = num;
ref = 20;
cout << "val : " << num << endl;
cout << "ref : " << ref << endl;
cout << "val : " << &num << endl;
cout << "ref: " << &ref << endl;
return 0;
}
|
변수 num과 참조자 ref가 동일한 메모리 공간을 참조하게 되며 주소값도 같음을 알 수 있다.
참조자의 수에는 제한이 없으며, 참조자를 대상으로 참조자를 선언하는 것도 가능
참조자의 선언 가능 범위
참조자는 변수에 대해서만 선언 가능. (배열이 아닌 배열요소도 변수로 간주)
선언과 동시에 누군가를 참조해야 함.
int &ref=20; (x)
상수를 대상으로 참조자 선언 불가
int &ref; (x)
미리 참조자를 선언후, 후에 누군가를 참조하는 것도 불가
int &ref=NULL; (x)
NULL 초기화 불가
배열 요소(배열이 아님)를 대상으로 참조자 선언
#include <iostream>
using namespace std;
int main()
{
int arr[3] = { 1,2,3 };
int &ref1 = arr[0];
int &ref2 = arr[1];
int &ref3 = arr[2];
cout << ref1 << endl;
cout << ref2 << endl;
cout << ref3 << endl;
return 0;
}
|
다음과 같이 포인터 변수를 대상으로 참조자 선언 가능
#include <iostream>
using namespace std;
int main()
{
int num = 12;
int * ptr = #
int ** dptr = &ptr;
int &ref = num;
int * (&pref) = ptr;
int ** (&dpref) = dptr;
cout << ref << endl;
cout << * pref << endl;
cout << ** dpref << endl;
return 0;
}
|
다음의 함수 정의는 Call-by-value도 될수 있고 Call-by-reference도 될 수 있다.
int * SimpleFunc(int * ptr)
{
. . . .
}
다음과 같이 정의되면 Call-by-value
int * SimpleFunc(int * ptr)
{
return ptr+1;
}
주소 값이 전달되었냐가 아닌, 주소값이 참조의 도구로 사용되었냐가 구분의 기준이 됨
c++에서는 주소값을 이용한 Call-by-reference외에도 (혹자는 이를 Call-by-address라 부르기도 한다)
참조자를 이용한 Call-by-reference도 존재한다.
참조자를 이용한 Call-by-reference
#include <iostream>
using namespace std;
void SwapByRef2(int &ref1, int &ref2)
{
int temp = ref1;
ref1 = ref2;
ref2 = temp;
}
int main()
{
int val1 = 10;
int val2 = 20;
SwapByRef2(val1, val2);
cout << "val 1 : " << val1 << endl;
cout << "val 2 : " << val2 << endl;
return 0;
}
|
참조자를 이용해 값을 증가시키는 함수, 부호를 바꾸는 함수 정의하고
각 함수의 호출결과 확인
#include <iostream>
using namespace std;
void Func(int &ref)
{
ref++;
}
void Func2(int &ref)
{
ref = ref*(-1);
}
int main()
{
int val1 = 10;
Func(val1);
cout << "val 1 : " << val1 << endl;
Func2(val1);
cout << "val 1 : " << val1 << endl;
return 0;
}
|
포인터 변수 ptr1, ptr2가 가리키는 대상이 바뀌도록 하는 SwapPointer 함수 정의하고 결과를 출력해 확인
#include <iostream>
using namespace std;
void SwapPointer(int * (&ptr1), int *(&ptr2))
{
int * temp = ptr1;
ptr1 = ptr2;
ptr2 = temp;
}
int main()
{
int val1 = 10;
int val2 = 20;
int * ptr1 = &val1;
int * ptr2 = &val2;
SwapPointer(ptr1, ptr2);
cout << "ptr 1 -> " << *ptr1 << endl;
cout << "ptr 2 -> " << *ptr2 << endl;
return 0;
}
|
참조자 기반 함수 정의의 단점
int num=24;
HappyFunc(num);
cout<<num<<endl;
C언어 관점에서 본다면 100% 24가 출력될거 같지만, C++에서는 얼마가 출력될지 알 수 없다.
void HappyFunc(int prm) { . . . .} // 위와 같이 함수가 정의되어 있다면 24가 출력되겠지만
void HappyFunc(int &ref) { . . . . } // 참조자가 매개변수에 있다면 num에 저장된 값을 변경할 수도 있다.
그렇기 때문에 참조자를 사용하는 경우 함수 원형을 확인해야하고, 참조자가 매개변수 선언에 있을 때
값의 변화가 일어나는지 함수의 몸체(body)까지 살펴볼 필요성이 생긴다.
이는 함수의 호출문장을 보고 함수 특성을 판단할 때 단점이 된다.
따라서 참조자의 활용이 쉬움에도 명확한 코드를 위해 포인터를 사용하는 경우도 있다.
다음과 같이 참조자 ref에 const 키워드를 이용하면 함수의 몸체까지 들여다볼 필요없이, 함수의 원형을 확인하는 정도로 그칠 수 있다.
void HappyFunc(const int &ref) { . . . . } // 함수 HappyFunc내에서 참조자 ref를 이용한 값의 변경은 하지 않겠다는 const 선언
Return Type이 Reference Type인 경우
#include <iostream>
using namespace std;
int & RefRetFuncOne(int &ref)
{
ref++;
return ref;
}
int main()
{
int num1 = 1;
int &num2 = RefRetFuncOne(num1); // 함수호출 후 참조자를 반환하며, 이를 참조자 &num2에 저장
num1++; // 변수 num1과 참조자 num2의 값을 1씩 증가, 각각 3이 됨
num2++; // 마찬가지로 1씩 증가해 각각 4가 됨
cout << "num1 : " << num1 << endl;
cout << "num2 : " << num2 << endl;
return 0;
}
|
Output:
바로 위 예제와 달리 일반 변수에 참조자 반환값 저장
#include <iostream>
using namespace std;
int & RefRetFuncOne(int &ref)
{
ref++;
return ref;
}
int main()
{
int num1 = 1;
int num2 = RefRetFuncOne(num1); // 함수호출 후 참조자를 반환하지만 참조자가 아닌 일반변수를 선언하고 반환값을 저장
num1+=1;
num2+=100;
cout << "num1 : " << num1 << endl;
cout << "num2 : " << num2 << endl;
return 0;
}
|
반환형이 참조형인 경우
: 위의 두 예제와 같이 반환대는 대상을 참조자로 받거나 변수로 받을 수 있다.
반환형이 참조자가 아닌 경우
: ref를 반환하든, 변수에 저장된 값을 반환하든 차이는 없다.
int RefRetFuncTwo(int &ref) // 반환형이 참조형( int & )은 아님
{
ref++;
return ref;
}
반환형이 값의 형태라면 참조자로 그 값을 받을 수 없다.
(상수를 참조하게 되므로)
int num2=RefRetFuncTwo(num1); (o)
int &num2=RefRetFuncTwo(num1); (x)
아래와 같이 지역변수를 참조의 형태로 반환하는 것은 문제가 된다.
int & RetuRefFunc(int n)
{
int num=20;
num+=n;
return num; // 지역변수의 반환
}
int &ref = RetuRefFunc(10); // ?? ref가 참조하는 대상이 소멸
const 참조자의 잘못된 사용
const int num=20;
int &ref=num;
ref+=10;
cout<<num<<endl;
위에서 num을 const선언해놓고 참조자를 통해 값을 변경하는 것은 const 선언의 이유를 잃게 하므로 에러
따라서 const 참조자는 프로그램의 안정성을 위해 다음과 같이 쓰는것이 좋다.
const int num=20;
const int &ref=num; // ref로 참조는 하되 값을 변경하지 않겠단 의미
const int &ref=50; // const참조자를 통해 상수 참조 가능
const참조자가 상수를 참조가능한 이유
: 리터럴 상수는 참조자로는 참조할 수 없게 되어 있다.
하지만 const참조자로 참조할 경우에는 허용하며, 상수를 메모리 공간에 임시적으로 저장한다.
이러한 것이 가능하도록 한 이유는 아래와 같이 매개변수 형이 참조자인 경우에 상수를 전달할 수 있도록 하기 위함이다.
int Adder(const int &num1, const int &num2)
{
return num1 + num2;
}
malloc과 free함수를 대신하는 new와 delete
c언어에서의 malloc과 free 함수
크기를 바이트 단위로 계산하지않고 type에 맞게 할당
int * ptr=new int;
double *arr=new arr[7];
이렇듯 new연산자로 할당된 메모리 공간은,
아래와 같이 delete함수 호출을 통해 소멸한다.
delete ptr; // 앞서 할당된 int형 변수 소멸
delete []arr; // 앞서 할당된 double형 배열 소멸
c에서 heap영역으로의 접근은 pointer를 통해서만 이루어졌지만 c++에서는 reference를 통한 접근도 가능.
참조자를 통해 heap에 접근하기
int * ptr = new int;
int & ref = *ptr; // heap영역에 할당된 변수에 대한 참조자 선언
ref=20;
cout<< * ptr << endl;
C++에서 C언어 표준함수 호출하기
c언어에 대응하는 c++ 헤더파일의 이름 규칙
: c를 더하고 .h를 빼면 된다.
C언어 헤더 C++ 헤더
#include <stdio.h> #include <cstdio>
#include <stdlib.h> #include <cstdlib>
c++의 표준함수는 std라는 namespace안에 선언되어 있음
또한 표준 C에 대응하는 표준 C++함수는 C++문법을 기반으로 변경 및 확장되었다 (함수 오버로딩을 통해 개선하는 등)
따라서, 가급적 C++에 표준함수를 호출하는 것이 좋다.
'Study > C++' 카테고리의 다른 글
생성자와 소멸자, 클래스 (0) | 2016.09.26 |
---|---|
class (0) | 2016.09.25 |
CPP-Object Oriented Programming (객체지향 프로그래밍) (0) | 2016.09.23 |
c++ Class (0) | 2016.09.22 |
c++ 기초 (0) | 2016.09.19 |