기초 CS - 포인터 2

킴스코딩클럽·2022년 10월 12일
1

CS기초 시리즈

목록 보기
31/71

포인터의 포인터

포인터 타입을 가리키는 포인터

??? >> 포인터 변수 >> 일반 변수

int*** >> int** >> int*
int main()
{
	int x{10};
	int* p{&x}; //참조
	*p = 1; //역참조
	
	int** p{ &p }; //포인터의 포인터
    
    std::cout<<x 
    // x의 값이므로 10
    std::cout<<*p
    // p가 가리키는 곳의 값 : 10
    std::cout<<pp
    //pp의 값
    std::cout<<*pp
    //pp가 가리키는 값
    std::cout<<*(*pp)
    //p의 값 10
    //pp를 들어가서 역참조해서 그 역참조한 것을 다시 역참조
    //컴파일러는 오른쪽에서 왼쪽 순서로 만들어지기 때문

}

구조체 포인터(화살표 연산자

	int x{ 10 };
	int* p{ &x };
	struct Item
	{
		int price;
		int quantity;
	}; //구조체

	Item sword{ 100,1 };

	Item* pItem{ &sword };
	//구조체의 포인터

	std::cout << *pItem.price; 
	//컴파일러는 *(pItem.price)로 이해중임
	//오류 : 연산자 우선순위 포인터 연산자를 먼저 할것이냐 .연산자를 먼저할것이냐?
	std::cout << (*pItem).price;
	//무엇은 먼저해야하는가? :역참조 먼저하고 그 다음 프라이스에 접근하려고하는 것
    pItem->price; 
    // 화살표 연산자

(*구조체포인터).멤버 : .연산자 우선순위가 높기 때문
그래서 c에서는 화살표 연산자를 추가함 : ->
-> 역참조 후 멤버 접근하기


상수와 포인터

constant variable : 상수 변수

상수를 가리키는 포인터

포인터가 상수 - 상수 포인터
int* const p;

	const int myPrecious{ 10 };
	const int x{ 20 };

	const int* p{ &myPrecious };
	//상수를 가리키는 포인터
	//(const int)* : 포인터는 상수가 아님, 대상이 상수
	// const (int*) : 포인터가 상수, 대상은 일반적인 int
	//둘 중에 무슨 의미일까? : (const int)* 가리키는 대상이 상수이다
	p = &x;
	p = &myPrecious;
	//대상이 상수이므로
	*p = 1; //불가능함
	//역참조로 들어가서 값의 수정은 할 수 없음 : 가리키는 대상이 상수이기 때문

	//const(int*p) :포인터가 상수,대상은 int
	//상수 포인터 - 타입 뒤에 const붙임
	int* const p;

상수 포인터

상수 포인터는 역참조로 값을 변경할 수 없다
상수처럼 접근하는 효과가 나옴

	int x{ 10 }, y{ 20 };
	const int* p1{ &x }; 
	//상수를 가리키는 포인터

	p1 = &y;
	*p1 = 10; //역참조 자체는 가능하지만 readonly(읽기전용)으로 역참조로 수정할 수는 없음
	std::cout<<*p1
   //x,y 자체는 상수가 아님 : x자체는 바뀌지 않음
   //하지만 포인터로 접근할 때는 상수처럼 접근하는 효과가 나옴

포인터가 상수라면 다른 것을 가리킬 수 없음

	int* const p2{ &x };
	p2 = &y; //불가능
	*p2 = 10; //가능

역참조로 값 변경도 안되고
다른것을 가리키는 것으로 바꿀 수 없음

const int* const p3{ &x };
	p3 = &y;
	*p3 = 10;

포인터의 사용이유

참조(reference), 배열(array)
= 메모리 관리

Referece

  • call by value(값의 복사) vs
  • call by reference(주소만 사용)

call by value

void Swap(int x, int y)
{
	
	int temp;
	temp = x;
	x = y;
	y = temp;

	
	
}

int main()
{
	Swap(1, 2);
    std::cout<<x<<y;
    //변경되지 않음
}

값이 복사되어 넘어오기 때문에 원래 값은 변하지 않음


call by reference

void Swap(int *x, int *y)
{
	
	int temp{*x};
	*x = *y;
	*y = temp;

	
	
}

int main()
{
	int x{ 10 }, y{ 20 };
	Swap(&x,&y);
    std::cout<<x<<y;
    //값이 변경됨
}

주소만 사용하여 값에 의한 복사가 없다는 장점(성능 향상/최적화)
cpu와 메모리 낭비를 줄여줌
주소가 넘어오기 때문에 주소를 역참조할 수 있어 매개 변수를 직접 바꿀 수 있음


c++의 포인터

c언어의 포인터를 발전/계승
포인터 타입 -> 참조 타입(reference type)

참조 타입 : 타입& 변수명 => int& ref{a};

  • 선언과 동시 반드시 초기화
  • 초기화 이후에는 다른 변수를 참조할 수 없음
  • 포인터 표기법 없어짐(&,*)
  • 상수만 가능함(한 번 가르키면 못바꿈) > 특수한 상황에서만 사용
  • 실제로 참조는 함수의 매개변수에서 사용함
  • 참조 매개변수는 값을 받지 못함 무조건 주소만 넘어감
	//c++ reference type
	int a{ 1 };
	//int*p{&a};

	int& ref; 
	//주소를 씀 : 참조의 개념
	//참조형은 선언과 동시에 반드시 초기화가 필요함
	//초기화 이후에는 다른 변수를 참조할 수 없음
	//상수의 개념

	int& ref{ a };
	//&쓰지 않아도 됨
	ref = 3;

포인터 버전

void Swap(int *x, int *y)
{
	
	int temp{*x};
	*x = *y;
	*y = temp;

	
	
}

int main()
{
	int x{ 10 }, y{ 20 };
	Swap(&x,&y);
    std::cout<<x<<y;
    //값이 변경됨
}

참조형 버전

void Swap(int& x, int& y) //참조 버전 : 포인터 버전과 비교해보기
{
	int a;
	x = &a; //참조형 변수는 다른 변수를 참조하도록 바꾸지않음

	int temp{ x }; //역참조 중임
	x = y;
	y = temp;
}

int main()
{
	int x{ 10 }, y{ 20 };
	Swap(x, y); //주소 필요없음
	std::cout << x << y;
	//값이 변경됨
}

정리

c언어 포인터
int x;
int p = &x;
p = 1;


c++ 참조형
int x;
int& p{x};
p = 1;


참고(c#,java)
int x;
int ref = x;
x=1;

아래로 갈수록 더 쉬워짐 (기호가 없음) but 개념으로 참조 구분이 어려움


const int p1{&x}; 상수int를 가르키는 포인터
int
const p2{&x}; int를 가르키는 상수 포인터


int y{10};
const int& ref{y}; : 상수를 참조하는 타입

int& const ref2{y};
없음 : 참조는 선언과 반드시 초기화 후 다른걸 참조 불가>> 참조는 상수포인터가 필요없음 기본으로 그 의미를 가지고 있기 때문


int& refmyValue;
참조형 : 사용법이 일반 변수와 같음(일반 변수와 구분해서 ref붙이는 방법도 많이 사용됨)
int * pmyValue;
포인터형 : p붙여서 신경써서 다루기 위해서
int value;
일반변수

profile
공부 기록용

0개의 댓글