[Chap 02] C언어 기반의 C++
💎 새로운 자료형 bool
#include <iostream>
int main()
{
int num = 10;
int i = 0;
std::cout << "true " << true << std::endl;
std::cout << "false: " << false << std::endl;
while (true)
{
std::cout << i++ << ' ';
if (i > num)
{
break;
}
std::cout << std::endl;
std::cout << "sizeof 1: " << sizeof(1) << std::endl;
std::cout << "sizeof 0: " << sizeof(0) << std::endl;
std::cout << "sizeof true: " << sizeof(true) << std::endl;
std::cout << "sizeof false: " << sizeof(false) << std::endl;
return 0;
}
}
>>>
true 1
false: 0
0
sizeof 1: 4
sizeof 0: 4
sizeof true: 1
sizeof false: 1
true는 1, false는 0로 처리가 된다.
그래서 true + false는 1 + 0으로 처리될 수 있으나 일반적으로는 다른 데이터형처럼 사용된다.
#include <iostream>
bool IsPos(int num)
{
if (num <= 0)
{
return false;
}
else
{
return true;
}
}
int main()
{
bool isPos;
int num;
std::cout << "Input number: ";
std::cin >> num;
isPos = IsPos(num);
if (isPos)
{
std::cout << "Positive number" << std::endl;
}
else
{
std::cout << "Negative number" << std::endl;
}
return 0;
}
>>>
Input number: 12
Positive number
💎 참조자의 이해
#include <iostream>
int main()
{
int num1 = 2010;
int &num2 = num1;
num2 = 3047;
std::cout << "VAL: " << num1 << std::endl;
std::cout << "REF: " << num2 << std::endl;
std::cout << "VAL: " << &num1 << std::endl;
std::cout << "REF: " << &num2 << std::endl;
return 0;
}
>>>
VAL: 3047
REF: 3047
VAL: 0x61ff08
REF: 0x61ff08
& 연산자는 변수의 주소 값을 반환하는 연산자이기도 하지만 새로 선언되는 변수의 이름 앞에 등장하면 이는 참조자의 선언 을 뜻하게 된다.
참조자는 변수를 대상으로만 선언이 가능하다. ‘/’
#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;
}
>>>
1
2
3
배열 하나의 요소만 참조하는 것도 가능하다.
🔆 포인터를 이용한 Call-by-reference
#include <iostream>
void SwapByRef(int *ptr1, int *ptr2)
{
int temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
}
int main()
{
int val3 = 10;
int val4 = 20;
SwapByRef(&val3, &val4);
std::cout << "val1: " << val3 << std::endl;
std::cout << "val2: " << val4 << std::endl;
return 0;
}
>>>
val1: 20
val2: 10
포인터를 이용한 함수를 보면은 인자값을 꼭 &를 붙혀서 사용해야됨을 알 수 있다. 당연한 사실이다. val3과 val4는 값이고, 매개변수로 전달되어야 하는 값은 포인터이기 때문이다.
🔆 참조자를 이용한 Call-by-reference
하지만 참조자를 이용한 함수의 경우는 다르다. 인자값을 잘 보면 알 수 있다.
#include <iostream>
void SwapByRef2(int &ref1, int &ref2)
{
int temp = ref1;
ref1 = ref2;
ref2 = temp;
}
int main()
{
int val1 = 10;
int val2 = 20;
SwapByRef2(val1, val2);
std::cout << "val1: " << val1 << std::endl;
std::cout << "val2: " << val2 << std::endl;
return 0;
}
>>>
val1: 20
val2: 10
인자로 전달되는 값은 그냥 값을 전달하는 것과 동일하게 하면 된다. 이렇게만 된다면 포인터보다는 참조자를 사용하는 것이 훨씬 유리한 것 같다.
굳이 머리를 써서 포인터를 가리키는지 값을 가리키는지 보지 않아도 되기 때문이다. 하지만 이런 참조자를 이용한 방식에도 단점이 있다.
함수 내에서 값이 변경되는지 아닌지를 인자값만 보고는 알 수 없다. 따라서 int 앞에 const를 붙혀서 이를 명시하는 것이 좋다.
void HappyFunc(const int &ref)
{
...
}
🔆 반환형이 참조형인 경우
총 8가지 경우로 나뉠 수 있을 것 같다.. 근데 int 형은 ,,,,,아 ㅅ ㅈㄴ 헷갈려,,,,,,,,,,,,,,,,,,,,,,,,근데! int&형의 함수는 int, int&형으로 리턴값을 전달할 수 있지만 int형의 함수는 int형에게만 리턴할 수 있다.
int &RefRetFuncOne(int &ref)
{
}
int RefRetFuncTwo(int &ref)
{
}
int &RefRetFuncThree(int ref)
{
}
int RefRetFuncFour(int ref)
{
}
int num0 = 1;
int &num1 = RefRetFuncOne(num0);
// int &num2 = RefRetFuncTwo(num0);
int &num3 = RefRetFuncThree(num0);
// int &num4 = RefRetFuncFour(num0);
// int num5 = RefRetFuncOne(num0);
int num6 = RefRetFuncTwo(num0);
// int num7 = RefRetFuncThree(num0);
int num8 = RefRetFuncFour(num0);
num0는 위의 줄과 상관없이 모두 0이라고 가정한다.
앞에 참조값이 들어가 있지 않는다면 딱 함수에서 리턴한 값으로 초기화되는 형식이다. 그 이외의 값의 증감은 상관없다.
num1의 경우는 num0의 값의 참조값이 리턴되었으므로 num1이 증가하면 같이 num0도 증가하게 된다.
#include <iostream>
int &RefRetFuncOne(int &ref)
{
ref++;
return ref;
}
int main()
{
int num1 = 1;
int &num2 = RefRetFuncOne(num1);
num1++;
num2++;
std::cout << "num1: " << num1 << std::endl;
std::cout << "num2: " << num2 << std::endl;
}
>>>
num1: 4
num2: 4
💎 new & delete
malloc & free를 대신해서 C++에서는 new & delete를 사용한다.
c코드
#include <iostream>
#include <string.h>
#include <stdlib.h>
char *MakeStrAdr(int len)
{
char *str = (char *)malloc(sizeof(char) * len);
return str;
}
int main()
{
char *str = MakeStrAdr(20);
strcpy(str, "I am so happy~");
std::cout << str << std::endl;
free(str);
return 0;
}
이렇게 동적 할당을 하는 것은 2가지 문제가 있다.
- 할당된 대상의 정보를 무조건 바이트 크기로 전달해야 된다.
- 반환형이 void 형 포인터이기 때문에 적절한 형 변환을 거쳐야 한다.
C++ 코드
#include <iostream>
#include <string.h>
char *MakeStrAdr(int len)
{
// char * str = (char*)malloc(sizeof(char)*len);
char *str = new char[len];
return str;
}
int main()
{
char *str = MakeStrAdr(20);
strcpy(str, "I am so happy~");
std::cout << str << std::endl;
// free(str);
delete[] str;
return 0;
}
cpp에서는 더이상 malloc을 통해서 메모리 할당 받는 것이 아닌 new를 통해서 메모리를 할당받고, delete를 통해서 메모리를 해제한다.
💎 C++에서 C언어의 표준함수 호출하기
c를 더하고 h를 빼라
- stdio.h -> cstdio
- stdlib.h -> cstdlib
- math.h -> cmath
- string.h -> cstring
그래서 std라는 이름공간에 내용이 선언되어 있다는 사실만 제외하면 c++의 헤더는 C 언어의 헤더와 별 차이가 없다.
#include <cmath>
#include <cstdio>
#include <cstring>
int main()
{
char str1[] = "Result";
char str2[30];
std::strcpy(str2, str1);
std::printf("%s: %f\n", str1, std::sin(0.14));
std::printf("%s: %f \n", str2, std::abs(-1.25));
return 0;
}
>>>
Result: 0.139543
Result: 1.250000
댓글남기기