Passing Points to a Function
중요한 Part이다.★★★★★
◆ 포인터를 함수의 인자로 전달
● Pass-by-address / 변수의 주소를 전달
#include <iostream>
using namespace std;
void double_data(int*);
int main()
{
int value = 10;
cout << value << endl; // 10
double_data(&value);
cout << value << endl; // 20
return 0;
}
void double_data(int* int_ptr)
{
*int_ptr *= 2;
}
void double_data(int* int_ptr)에서 *int_ptr *= 2; 를 선언하게 되면
int value의 값이 10에서 2배를 곱한 20으로 변한다.
그리고 함수가 끝나면 메모리 값은 해제된다.
함수 선언이 끝나서 메모리 할당이 해지되어도 그전에 있는 메모리 값은 그대로 둔다.
원상복구는 따로 하지 않는다.
※ 주소를 가지고 있기에 호출 Stack 밖의 값도 바꿀 수 있다.
(그렇기에 메모리를 쓰게 되면 무서운 일이 일어날 수 있기에
단순 디스플레이는 const를 쓰는 게 중요하다.)
Returning a Pointer
중요한 Part이다.★★★★★
◆ 포인터의 반환
● 인자로 전달된 데이터(포인터)를 반환할 수 있다.
int* largest_int(int* int_ptr1, int* int_ptr2)
{
if (*int_ptr1 > *int_ptr2)
return int_ptr1;
else
return int_ptr2;
}
● 함수 내부에서 동적으로 할당된 메모리의 주소를 반환할 수 있다.
#include <iostream>
using namespace std;
int* create_array(int size, int init_value = 0);
int main()
{
int* my_array = nullptr;
my_array = create_array(100, 10);
delete[] my_array;
return 0;
}
int* create_array(int size, int init_value = 0)
{
int* new_storage = nullptr;
new_storage = new int[size];
for (int i = 0; i < size; ++i)
{
*(new_storage + 1) = init_value;
}
}
● (주의!) 지역 변수에 대한 포인터 반환은 안된다!
#include <iostream>
using namespace std;
int* dont_do_this();
int main()
{
int* a = nullptr;
a = dont_do_this();
cout << *a << endl;
}
int* dont_do_this()
{
int num = 10;
int* num_ptr = #
return num_ptr;
}
만일 저 파일을 실행한다면 이렇게 스택 메모리가 나올 것이다.
다만 int* dont_do_this() 함수가 끝나면
return 값인 num_ptr은 어떻게 반환받을 수 있는가?
못 받는다.
하지만 컴파일러 C++20 은 받을 수 있다.
나의 컴파일러로는 10이라는 출력값이 나왔다..
Pointer Cautions (포인터 사용 시 주의사항)
◆ 초기화의 필요성
int* int_ptr; // anywhere int* int_ptr = nullptr; // Safe. ... *int_ptr = 100; // in VS, compiler protects |
◆ 허상 포인터(dangling pointer)
● 두 포인터가 동일 데이터를 가리키다, 하나의 포인터가 메모리를 해제할 경우
● 지역 변수를 참조하고, 호출 스택이 끝나는 경우
◆ new의 실패
● 가끔 발생할 수 있음. 이런 경우 예외 처리 필요 (후반 강의)
◆ 메모리 누수(memory leak)
● 동적 할당으로 사용한 메모리는 반드시 해제해야 함.
허상 포인터 예시
int main()
{
int* val = new int;
*val = 10;
int* val2 = val;
cout << val << endl; //000002194B786070
delete val2;
val2 = nullptr;
cout << val << endl; //000002194B786070
}
원래는 val 주소값이 나오면 안 되지만
C++20에서는 나온다.
원래는 val2를 해제하고 val를 볼 경우 쓰레기 값이 나와야 한다.
(Summary) Pointers
◆ 포인터 선언 ( 포인터는 변수, * 사용, nullptr 초기화 )
◆ 주소로의 접근 ( &, 주소의 크기와 데이터의 크기를 구분 )
◆ 역참조 (*, 포인터가 가리키는 데이터를 접근 )
◆ 동적 메모리 할당 ( new, delete, 런타임에 힙 메모리 사용 )
◆ 포인터와 배열 ( 주소값의 증감 offset )
◆ 포인터와 const (3가지 case , 주소/데이터 값의 const)
◆ 포인터의 pass-by-address( 전달된 포인터, 내부에서 동적 할당한 포인터, 지역변수 반환 금지 )
◆ 주의사항 ( 초기화, 허상, new 실패, 메모리 누수 )
https://youtu.be/PpHH4XyoNgw?si=AuNTsG_1PrIPDprG
'C++ > C++ : Study' 카테고리의 다른 글
C++ 포인터 참조자 (6) 참조자 (0) | 2024.09.22 |
---|---|
c++ 포인터 참조자 (1) 개요 (0) | 2024.09.22 |
C++ 포인터 참조자 (4) 배열과 포인터, Const (0) | 2024.09.21 |
C++ 포인터 참조자 (3) 동적 할당 (1) | 2024.09.18 |
C++ 포인터 참조자 (2) 역참조 (1) | 2024.09.16 |