공부하기 싫을 때 쓰는 블로그
[cppPrimer요약] functions basic 본문
part 1_ Theory
lifetime of objects
function parameters 와 function body에 정의된 local variables은 기본적으로
function이 return 하면 사라진다. (destroyed)
만약 function이 exit 한 후에도 사라지지 않고 프로그램이 종료될 때까지 유지되는
variable 을 만들고 싶으면 static을 쓴다.
아래 count_calls 함수는 자신이 호출된 횟수를 function body에 static variable로 저장하고 있다.
#include <iostream>
using namespace std;
size_t count_calls() {
static size_t ctr = 0;//this lives across function calls
return ++ctr;
}
int main() {
for (size_t i = 0; i != 10; ++i)
cout << count_calls() << endl;
}
Passing parameters
C에서는 주로 pointer를 통해 pass-by-reference 했다면,
cpp 에서는 주로 reference를 통해 pass-by-reference(어.. 써놓고 나니까 너무 당연하다)를 한다.
우리가 reference에 대해서 기억해야 할 것은
- reference는 어떤 object에 대한 또 다른 이름 (alias) 이다.
- reference는 한번 어떤 object를 가리키도록 되면 (bound to) 다른 object를 가리키지 못한다.
또 passing-by-reference에 대해서 기억해야 할 것은
1. 어떤 function이 그에 pass된 reference를 통해서 그에 bound 된 object를 바꾸지 않는다면,
reference to a const 를 쓰자.
//comparing the length of two strings.
bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}
reminder: const reference의 규칙
1. const int 에 대한 ref를 (plain) int에 bound 할 수 있다.
하지만 이 ref를 통해 그 bound 된 int값을 바꿀 수 없다.
(이는 pointer도 마찬가지)
int i = 0;
const int &ri = i; //legal
ri = 1; //illegal: ri is a reference to const.
2. plain int 에 대한 ref 에 const int에 대한 ref를 assign 할 수 없다. (이 역시 pointer도 마찬가지)
int i = 0;
const int &cri = i;
int &ri = cri; //illegal. cri is a ref to const, ri is not.
2. 함수가 여러 값을 return 할 때 reference를 통해 하자!
이 예시는 string s 에서 특정 char c의 첫번째 위치(index) 와 c의 개수(occurs) 를 구한다.
index는 return을 통해 반환하고,
occurs는 reference를 parameter로 넣어주고, 함수 안에서 값을 준다!
//returns the index of the first occurence of char c in string s
//also by -> occur <- returns the number of occurences.
string::size_type find_char(const string& s, char c,
string::size_type& occurs) {
auto index = s.size(); //will be returning s.size if not found.
occurs = 0;
for (decltype(index) i = 0; i != s.size(); ++i) {
if (s[i] == c) {
if (index == s.size())//not yet found
index = i;//will return the first index.
++occurs; //increment every occurence of c.
}
}
return index;
}
* Array Parameters
array를 parameter로 사용할 때에는, 첫 element에 대한 pointer로 pass-by-ref 합니다!
왜냐면 array는 value-copy 할 수 없기 때문이다 (한 array 에 다른 array를 assign 할 수 없다)
reminder: array에 대해 기억해야 할 것들
1. array는 copy 할 수 없다.
int a[] = {0, 1, 2};
int b[] = a; //illegal: cannot initialize with an array.
int c[3];
c = a; //illegal: cannot assign an array
2. array 는 pointer 처럼 취급한다.
int ia[] = {0, 1, 2}
auto ia2(ia); //ia2 is int* pointing to first element of ia.
*ia2 = 1;
int *p = &arr[2]; //legal, p points to the last element of ia.
*(--p) = 1; //legal, p points to the second element of ia.
int *q = ia; //this is equal to int *q = &ia[0]. points to first element of array.
int *beg = begin(ia); //pointer to first element
int *end = end(ia); //pointer to ONE PAST LAST ELEMENT
3. references and pointers
일단 reference 들의 array 같은 건 없다.
하지만 1. reference to an array, 2. pointer to an array, 3. array of pointers 는 있다!
int a[] = {1,2,3};
int (&ra)[3] = a; //ra is a reference to a.
int (*pa)[3] = &a; //pa points to a.
int *ptrs[3]; // ptrs is an array of pointers to int.
//the inside - out rule: what's in the brackets tells you what type of variable it is.
//then look around.
int *(&arr)[3] = ptrs; //arr is a REFERENCE to an ARRAY of 3 int*s.
다음 3개의 function prototype은 같다. 왜냐하면 array 의 이름은 곧
array의 첫 element의 pointer로 해석되기 때문이다.
void print(const int*);
void print(const int[]);
void print(const int[10]);
int arr[2] = {0, 1};
print(arr);
마지막 줄의 [10] 에서 10 은 무시된다. 단지 documentation 용으로 쓰일 수는 있다.
그럼 자연스럽게 궁금증이 생긴다..
array는 pass by reference,, 그럼 진짜 array의 reference, (&arr)을 주면 어떨까?
위의 pointer 방식과 가장 다른 점은
[sz] 의 sz 값까지 reference type의 일부가 된다.
즉, void print(const int (&arr)[10]); 은 진짜 10개짜리 array에 대한 reference만 받는다.
*processing from the beginning to the end of an array
function에 넘겨진 array의 각 element들을 process 해야 한다고 하자.
크게 두가지 상황이 있는데, 첫번째 상황은 array 자체에 대한 reference를 넘겨받았을 때이고,
두번째는 array를 pointer취급하여 첫 element에 대한 pointer를 넘겨받았을 때이다.
reference에 대해서는 비교적 간단하다. for문을 사용하는 것이 가장 쉽다.
void print(int (&arr)[10]){
for (auto elem: arr)
cout << elem << endl;
}
하지만 첫번째 element를 가리키는 pointer는 array의 dimension(크기)을 전혀 모른다.
물론, size_t size 와 같은 parameter로 직접 size를 넘겨주는 방법도 있지만,
약간 standard library convention을 따라하자면,
void print(const int *beg, const int *end){
while(beg != end) //end points to ONE PAST LAST.
cout << *beg++ << endl;
}
int j[] = {0, 1};
print(begin(j), end(j));
*the main function
main function 에서는 command line 에서 실행할 때 option을 주는 것과 같이,
각종 option들을 parameter로 받을 수 있는데, 물론 option을 여러개 줄 수 있다.
prog.exe를 실행하기 위해
prog -d -o ofile data0
를 cmd에 입력했다고 하자. main 함수가 있는 executable의 이름 prog 까지 합쳐 총 5개의
단어를 입력했는데, 이것은 main에서 아래와 같이 해석된다.
int main(int argc, char *argv[]) {...}
//argc = 5
/*
argv[0] = "prog",
argv[1] = "-d",
argv[2] = "-o",
... are C-style character strings(=pointers to an array of chars)
*/
declare in headers, define in src file!
function definiton은 그 함수의 return type, name, parameter types, 합쳐서 function prototype을
header file에 써주면 된다.. 근데 워낙 type들이 많아서..