[C++] C언어 기반의 C++(2)

C++ 2017. 12. 19. 10:46

1] Remind C
1. const의 의미 
const int num = 10; // 변수 num을 상수화
const int* ptr1 = &val1; // ptr1을 이용해서 val1의 값을 변경할 수 없음
int* const ptr2 = &val2; // ptr2를 상수화

2. 메모리 영역
- 데이터 영역: 전역변수가 저장되는 영역
- 스택: 지역변수 및 매개변수가 저장되는 영역
- 힙: malloc 함수 호출에 의해 프로그램이 실행되는 과정에서 동적으로 할당이 이뤄지는 영역.
- malloc & free : malloc 함수호출에 의해 할당된 메모리 공간은 free 함수호출을 통해서 소멸되지 않으면 해제되지 않는다. 


2] bool
: true와 false는 1과 0이 아니다. 

cout<<"true : "<<true<<endl;
cout<<"false : "<<false<<endl;

->
true : 1
false : 0

위 결과는 보고 true는 1, false는 0 이라고 생각할 수도 있다.

cout<<"sizeof 1: "<<sizeof(1)<<endl;
cout<<"sizeof 0: "<<sizeof(0)<<endl;
cout<<"sizeof true: "<<sizeof(true)<<endl;
cout<<"sizeof false: "<<sizeof(false)<<endl;

->
sizeof 1 : 4
sizeof 0 : 4
sizeof true : 1 
sizeof false : 1

위 결과를 보면 true, false의 크기와 0, 1의 크기가 다르다. 
true와 false가 정의되기 전에는 참과 거짓을 표현하기 위해서 1, 0으르 사용했기 때문에 이 둘을 출력하거나 정수의 형태로 형 변환하는 경우에 각각 1과 0으로 변환되도록 정의되어 있을 뿐이다. 

따라서 true와 false는 참과 거짓을 나타내는 목적으로 정의도니 데이터로 인식하는 것이 바람직하다. 


3] reference의 이해
: 할당된 하나의 메모리 공간에 다른 이름을 부여하는 것이다.

int &num2=num1;

위에서 "&"는 주소값을 반환하는 연산자가 아니라, 참조자의 선언을 뜻한다. 

int num1 = 1020;
int &num2 = num1;

num2 = 3047;

위 코드를 실행하면 num1, num2 모두 3047을 가진다. 이 결과는 하나의 메모리 공간을 똑같이 가리키니까 어찌보면 당연한 결과다.

1) 참조자(reference)를 이용한 Call-by-reference

void SwapByRef(int &ref1, int &ref2)
{
    int temp=ref1;

    ref1=ref2;
    ref2=temp;
}

2) 참조자(reference)를 이용한 Call-by-reference, 그리고 const 참조자
: 지금까지만 보면, 포인터를 이용한 Call-by-reference 보다 reference를 이용한 것이 더 간단하고 편해보인다. 하지만 단점이 있다.

int num=24;

HappyFunc(num);

위 코드에서 num의 값은 HappyFunc 함수 호출이후 어떤값이 될까? C라면 100프로 24가 되야 하지만, C++ 에서는 알수가 없다. reference를 이용한 Call-by-reference일 수도 있기 때문이다. 

이런 단점을 극복하려면 const 키워드를 사용해서 상수화 시켜야 한다. 

void HappyFunc(const int &ref) { ... }

위에서 ref는 함수내에서 값을 변경할 수 없다. 따라서, 함수 내에서 참조자를 통한 값의 변경을 진행하지 않은경우는 const 키워드를 사용해서 함수 원형만 봐도 값의 변형이 이뤄지지 않음을 알수있게 해라.

3) 반환형이 참조형(reference type)인 경우

int& RefRetFuncOne(int &ref)
{
    ref++;
    return ref;
}

int num1=1;
int &num2=RefRetFuncOne(num1);

num1++;
num2++;

cout<<"num1: "<<num1<<endl;
cout<<"num2: "<<num2<<endl;

-> 출력
num1: 4
num2: 4 

그런데 위 함수의 반환값을 int형으로 받으면 어떻게 되는지 보겠다.

num1 = 1;
int num2 = RefRetFuncOne(num1);

num1+=1;
num2+=100;

cout<<"num1: "<<num1<<endl;
cout<<"num2: "<<num2<<endl;

-> 출력
num1: 3
num2: 102

int&을 int형으로 받을 수 있고 이는 완전 다른 변수가 된다. 
그렇지만 int 반환값을 int&로 받을 수는 없다. 

다음은 잘못된 예를 들어보겠다.

int& RetuRefFunc(int n)
{
    int num = 20;
    
    num+=n;
    
    return num;
}

int &ref = RetuRefFunc(10);

int를 return 하지만 함수의 반환형으로 인해 int& 타입이 return 된다. 
그래서 ref 변수는 num 변수의 메모리를 같이 참조하게 되지만, num은 지역변수 이기 때문에 반환되어 ref 변수는 쓰레기값을 가지게 된다. 

4) 참조자(reference)의 상수 참조
: 리터럴 상수를 reference가 참조하려면 const 키워드를 사용해야 한다. 

const int *ref = 30;

위와같은 코드가 과연 필요한지 의문이 들기는 하지만 굳이 사용법을 찾아보겠다.

int Adder(const int& num1, const int& num2)
{
    return num1+num2;
}

위 함수에서 매개변수 둘을 더한값을 return하기 위해 변수 하나를 더 만드는것이 귀찮기 때문에 저런식으로 사용한 것이다. 


4] malloc & free를 대신하는 new & delete
: malloc, free를 사용해서 heap에 메모리를 할당, 해제하는것보다 조금 더 간단해졌다. 

int* ptr1 = new int; // int형 변수의 할당
double* ptr2 = new double; // double형 변수의 할당
int* arr1 = new int[3]; // 길이가 3인 int 형 배열의 할당
double * arr2 = new double[7]; //길이가 7인 double형 배열의 할당

delete ptr1;
delete ptr2;
delete []arr1;
delete []arr2;

* C++ 에서는 malloc, free 대신에 꼭 new, delete를 사용하자. 둘은 사용방식에 차이가 있어서 C++에서 malloc, free의 사용이 오류를 일으킬 수 있다. 

* heap에 할당된 변수도 참조자(reference)로 접근할 수 있다. 

int* ptr = new int;
int& ref = (*ptr);

ref = 20;

cout<<(*ptr)<<endl;

-> 출력
20




'C++' 카테고리의 다른 글

[C++] Friend와 Static 그리고 Const  (0) 2017.12.25
[C++] 복사 생성자(Copy Constructor)  (0) 2017.12.23
[C++] 클래스의 완성  (1) 2017.12.23
[C++] 클래스의 기본  (0) 2017.12.23
[C++] C언어 기반의 C++(1)  (0) 2017.12.18
Posted by 홍성곤
,