공부하기 싫을 때 쓰는 블로그

[cppPrimer요약] functions basic 본문

카테고리 없음

[cppPrimer요약] functions basic

Dalcomi20 2021. 9. 6. 18:57

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들이 많아서..

 

 

Comments