일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- c
- mysql
- BOF 원정대
- webhacking
- php
- Javascript
- hackerschool
- 인공지능
- 경제
- 파이썬
- hackthissite
- Shellcode
- 러닝스칼라
- BOF
- deep learning
- Scala
- backend
- Python
- 챗GPT
- flask
- 리눅스
- 웹해킹
- Web
- 러닝 스칼라
- ChatGPT
- 딥러닝
- 백엔드
- c++
- hacking
- Linux
- Today
- Total
jam 블로그
[C++] 002. C기반의 C++ 2 본문
I. 들어가기에 앞서서
강의에서 언급하는 내용이라 합니다. 혼자서 생각을 먼저 해보세요
const 키워드의 의미! 다음 문장은 어떤 의미를 지니는가?
- const int n = 10; //int n이 10으로 고정. 변수 상수화
- const int *n; //int *n을 고정 한다. (즉, 값은 고정 하나, 주소는 변경 가능하다.) 데이터 상수화
- int* const n; //*n을 고정합니다.(즉, 값은 변경 가능 하나, 주소가 고정이다.) 포인터 상수화
- const int* const n; //2번째, 3번째 줄 합친거와 같다.(즉, 값도 고정이고, 주소도 고정이다.)
스택이라는 메모리 영역은 어떤 용도로 사용되는 메모리 공간이며, 그 특징은?
- 지역변수, 매개변수 (컴파일 시 할당)
힙이라는 메모리 영역은 어떤 용도로 사용되는 메모리 공간이며, 그 특징은?
- 프로그래머 할당 (런타임 시 할당)
malloc과 free 함수를 사용해야만 하는 이유?(필요한 이유)
II. 새로운 형태의 자료형 bool
- 전통적인 방법의 true와 false
- #include <stdio.h>
- const int TRUE = 1;
const int FALSE = 0; - int IsPositive(int i)
{
if(i<0)
return FALSE;
else
return TRUE;
} - int main(void)
{
int num;
int result; - printf("숫자 입력 : ");
scanf("%d",&num); - result = IsPositive(num);
- if(result == TRUE)
printf("Positive numver \n");
else
printf("Negative number \n");
return 0;
}
- bool형을 이용한 true와 false
- #include <iostream>
- using namespace std;
- bool IsPositive(int i)
{
if(i<0)
return false;
else
return true;
} - int main(void)
{
int num;
bool result; - cout <<"숫자 입력 : ";
cin >> num; - result = IsPositive(num);
if(result == true)
cout <<"Positive number"<<endl;
else
cout <<"Negative number"<<endl;
}
- Bool형이 int 형으로 바뀌면 true 일때는 1 false 일때는 0가 나옵니다.
III. 레퍼런스의 이해
레퍼런스 라는 것이 무엇 일까?
- 이름을 지니고 있는 대상에게 지어주는 별명을 가리켜 레퍼런스라고 한다.
int &ref = val;
- val이라는 int형 변수의 이름에 ref라는 별명을 붙인 것이다. C++에서 레퍼런스를 선언할 때에도 &를 쓰인다.
- 레퍼런스의 특징
- #include<iostream>
- using namespace std;
- int main(void)
{
int val = 10;
int &ref = val;
val++; - cout<<"ref : "<<ref<<endl;
cout<<"val : "<<val<<endl;
ref++; - cout<<"ref : "<<ref <<endl;
cout <<"val : "<<val<<endl;
return 0;
}
ref는 val의 별명이기 때문에 둘다 같은 거라고 보면 된다. 따라서 ref가 증가하든 val가 증가하든 여튼 같은게 증가하는 것이다.
- 레퍼런스를 가지고 있는 연산은 레퍼런스가 참조하는 변수의 이름을 가지고 하는 연산과 같은 효과
레퍼런스의 제약
- 초기화를 시켜주지 않는다던가
- 상수가 오면 error
IV. 레퍼런스와 함수
- 포인터를 이용한 Call-By-Reference
- #include <iostream>
- using namespace std;
- void swap(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
} - int main()
{
int val1 = 10;
int val2 = 20; - cout <<"val1 : "<<val1<<' ';
cout<<"val2 : "<<val2 <<endl; - swap(&val1,&val2);
cout <<"val1 : "<<val1<<' ';
cout<<"val2 : "<<val2 <<endl;
return 0;
}
- 레퍼런스를 이용한 Call-By-Reference
- #include <iostream>
- using namespace std;
- void swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
} - int main(void)
{
int val1 = 10;
int val2 = 20; - cout <<" val1 : "<<val1<<' ';
cout<<"val2 : "<<val2 <<endl; - swap(val1,val2);
cout <<" val1 : "<<val1<<' ';
cout<<"val2 : "<<val2 <<endl;
}
레퍼런스를 이용한 성능의 향상
- 개인정보를 입출력하는 예제이다.
- #include <iostream>
- using namespace std;
- struct _Person{
int age;
char name[20];
char personalTD[20];
};
typedef struct _Person Person; - void ShowData(Person p)
{
cout<<"******* 개인 정보 출력 ********"<<endl;
cout<<"이 름 : "<<p.name<<endl;
cout<<"주민번호 : "<<p.personalTD <<endl;
cout<<"나 이 : "<<p.age<<endl;
} - int main(void)
{
Person man; - cout<<"이 름 : ";
cin>>man.name;
cout<<"나 이 : ";
cin>>man.age;
cout<<"주민번호 : ";
cin >> man.personalTD; - ShowData(man);
return 0;
}
위의 소스는 Call-By-Value의 기본방식인 값의 복사를 이용해서 만든 것이다.
- main 안에 ShowData에 man을 넘겨 주는데 man의 크기는 44바이트이다.(구조체 보면 int + 배열20+배열 20이다.)
- 만약 인자로 전달하는 변수가 늘어나고 크기고 커지면 프로그램 자체가 부담스러워 진다.
- 부담스러운 Call-By-Value를 대신하는 Call-By-Reference
- void ShowData(Person &p)
{
cout<<"******* 개인 정보 출력 ********"<<endl;
cout<<"이 름 : "<<p.name<<endl;
cout<<"주민번호 : "<<p.personalTD <<endl;
cout<<"나 이 : "<<p.age<<endl;
}
레퍼런스의 형태로 받게 되면, 이름만 하나 더 추가하는 것이므로 44바이트나 되는 크기의 복사는 발생하지 않는다.
- 추가 설명 : Call-By-Value는 값을 복사 하는 거기 때문에 44바이트나 복사를 해야하지만 레퍼런스로 설정하면 복사가 아닌 가리키는 식으로 되어서 복사가 일어나지 않는다.
- 그러나 ShowData는 그저 보여주는 함수이기 때문에 p값이 변경되면 안된다. 그것을 방지 하려면
- void ShowData(const Person &p)
{
cout<<"******* 개인 정보 출력 ********"<<endl;
cout<<"이 름 : "<<p.name<<endl;
cout<<"주민번호 : "<<p.personalTD <<endl;
cout<<"나 이 : "<<p.age<<endl;
}
const를 붙여 주면 값을 변경 할수 없다.
- 좀더 자세히 말하면 레퍼런스 p를 통한 데이터의 조작을 허용하지 않겠다는 것이다.
V. 레퍼런스를 리턴하는 함수의 정의
- 레퍼런스를 리턴하는 적절한 형태의 함수와 그 의미
#include <iostream>
using namespace std;
int& increment(int &val)
{
val++;
return val;
}
int main(void)
{
int n = 10;
int &ref = increment(n);
cout << "n : "<<n<<endl;
cout<<"ref : "<<ref<<endl;
return 0;
}
- n이 넘어가 면서 reference로 val라는 이름이 추가 되고 리턴 되면서 val는 ref라는 이름이 생기고 호출이 완료되면 val는 사라진다.
레퍼런스를 리턴하는 잘됫된 형태의 함수
- 지역변수는 레퍼런스로 리턴할 수 없다.
#include <iostream>
using namespace std;
int& function(void)
{
int val = 10;
return val;
}
int main(void)
{
int &ref = function();
cout<<"ref : "<<ref<<endl;
return 0;
}
실행은 되지만(또는 값이 제대로 나오지만) 컴파일시 waring이 뜬다. 왜냐하면 지역변수는 함수 호출후 사라지기 때문이다.
- waring을 뜨지 않게 하려면 static int val = 10; 를 치면 된다.
VI. new & delete
- new와 delete는 C에서 malloc과 free랑 비슷하다.
일단 malloc과 free에 대한 것이다.
#include <iostream>
using namespace std;
int main(void)
{
int size;
cout << "할당하고자 하는 배열의 크기 : ";
cin >> size;
int* arr = (int*)malloc(sizeof(int)*size);
for(int i=0;i<size;i++)
arr[i] = i+10;
for(int j=0;j<size;j++)
cout<<"arr["<<j<<"] = "<<arr[j]<<endl;
free(arr);
return 0;
}
- 위의 소스를 new와 delete로 바꾼다면 (별 다른 점은 없다. )
#include <iostream>
using namespace std;
int main(void)
{
int size;
cout << "할당하고자 하는 배열의 크기 : ";
cin >> size;
int *arr = new int[size];
for(int i=0;i<size;i++)
arr[i] = i+10;
for(int j=0;j<size;j++)
cout<<"arr["<<j<<"] = "<<arr[j]<<endl;
delete []arr;
return 0;
}
- 위에서 마지막에 delete []arr;이 있는데 delete[] arr; delete []arr; delete [] arr; 이런 식으로 쓰면 된다.
- NULL 포인터를 리턴하는 new 연산자
#include <iostream>
using namespace std;
int main(void)
{
int size;
cout << "할당하고자 하는 배열의 크기 : ";
cin >> size;
int *arr = new int[size];
if (arr == NULL)
{
cout << "메모리 할당 실패"<<endl;
return -1;
}
for(int i=0;i<size;i++)
arr[i] = i+10;
for(int j=0;j<size;j++)
cout<<"arr["<<j<<"] = "<<arr[j]<<endl;
delete []arr;
return 0;
}
위 소스는 if문이 추가 되었는데 if문이 메모리가 제대로 할당이 되었는지 확인 하는 조건문이다.
- 하지만 솔직히 if문 같은 비교문을 넣으면 성능만 저하 시킬수 있다고 판단을 한다.
- 그래서 매크로를 사용하여 다르게 처리를 해보자
#include <iostream>
using namespace std;
#define DEBUG 1 //테스트할 경우
//#define DEBUG 0 최종
int main(void)
{
int size;
cout << "할당하고자 하는 배열의 크기 : ";
cin >> size;
int *arr = new int[size];
#if DEBUG == 1
if (arr == NULL)
{
cout << "메모리 할당 실패"<<endl;
return -1;
}
#endif
for(int i=0;i<size;i++)
arr[i] = i+10;
for(int j=0;j<size;j++)
cout<<"arr["<<j<<"] = "<<arr[j]<<endl;
delete []arr;
return 0;
}
- 중간에 #if #endif 를 매크로와 함께 써서 테스트 일 경우에만 컴파일 되게 할 수도 있다.
'개발 및 관련 자료 > C' 카테고리의 다른 글
[C++] 004. 클래스의 완성 (0) | 2013.05.12 |
---|---|
[C++] 003. 클래스의 기본 (0) | 2013.05.12 |
[C++] 001. C기반의 C++ 1 (0) | 2013.05.12 |
[C] 26. 매크로와 전처리기 (0) | 2013.05.12 |
[C] 25. 메모리 관리와 동적 할당 (0) | 2013.05.12 |