VisualStudio/C++

[C++] 포인터와 참조

usingsystem 2024. 5. 13. 16:58
728x90

포인터

포인터는 메모리 주소를 저장하는 변수로 변수의 주소를 갖는 하나의 타입이다. 

포인터의 운영체제의 크기에 따라 4바이트 혹은 8바이트로 나뉜다.

포인터 기본

포인터는 타입 뒤에 *을 붙여 선언하고 &를 사용하여 주소를 추출해 포인터 변수에 담는다.

포인터 변수의 원본 값을 변경하기 위해서는 *을 붙여 변수 값을 수정할 수 있다. 이때 *을 포탈이라고 생각하고 주소를 가지고 있는 포인터 변수의 주소를 이용해 원본데이터로 접근하여 데이터를 변경해 준다.

	int num = 10; // 정수 변수 선언 및 초기화
    int *ptr; // 포인터 변수 선언

    ptr = # // num 변수의 주소를 포인터에 할당

    // 포인터를 통해 num 변수의 값을 출력
    std::cout << "num 변수의 값: " << *ptr << std::endl;

포인터 함수

포인터를 함수에 적용하면 값을 복사하지 않아도 되는 장점이 존재한다. 

이는 값을 복사하지 않기 때문에 메모리적인 이점을 얻을 수 있다.

이렇게 포인터로 구조체를 받아 안에 원본 매개변수를 접근할 때는 ->를 사용하여 접근할 수 있다. ->를 풀어서 쓴다면 (*info). Id로 쓸 수 있다.

struct Info
{
	int Id;
	int pwd;
};
int main()
{
	Info info1;
	info1 = CreateInfo1();

	Info info2;
	CreateInfo2(&info2);
}
Info CreateInfo1()//포인터 사용안했을 때
{
	Info ret;

	ret.Id = 100;
	ret.pwd= 100;

	return ret;
}

void CreateInfo2(Info* info)
{
	info->Id = 150;//(*info).Id = 150 과 같다
	info->pwd = 10;//(*info).pwd = 10 과 같다
}

포인터 함수와 *const

포인터를 매개변수로 갖는 함수에서 const를 *뒤에 붙일 수 있다. 이렇게 하면 해당 포인터 매개변수의 주소를 수정할 수 없음을 의미한다.

void CreateInfo2(Info* const info)
{
	info +=1;// 주소값을 변경할 수 없다.
    	info->Id = 150;// 데이터 변경 가능
	info->pwd = 10;// 데이터 변경 가능
}

포인터 함수와 const *

포인터를 매개변수로 갖는 함수에서 const를 *앞에 붙일 수 있다. 이렇게 하면 해당 포인터 매개변수가 가르키 데이터를 수정할 수 없다.

void CreateInfo2(const Info*  info)
{
	info->Id = 150;// 데이터 변경 불가능
	info->pwd = 10;// 데이터 변경 불가능

	info += 1;// 주소값을 변경할 수 있다.
}

참조

변수 또는 객체에 대한 별칭(alias)을 제공하는 개념입니다. 참조를 사용하면 기존 변수 또는 객체에 대해 별칭을 만들어 코드를 더 간결하고 읽기 쉽게 만들 수 있습니다.

참조기본

타입 뒤에 &를 사용하여 참조를 선언할 수 있다.

    int num = 10; // 정수 변수 선언 및 초기화
    int &ref = num; // 참조 변수 선언 및 초기화

    std::cout << "num 변수의 값: " << num << std::endl;
    std::cout << "ref 변수의 값: " << ref << std::endl;

    ref = 20; // 참조를 통해 변수 값 변경

    std::cout << "변경 후 num 변수의 값: " << num << std::endl;
    std::cout << "변경 후 ref 변수의 값: " << ref << std::endl;

또 한 참조는 포인터와 다르게 참조하는 대상이 없으면 선언할 수 없고 nullptr 개념이 존재하지 않는다.

정말로 없음을 표현하고 싶다면 참조보다는 포인터를 사용해야 한다.

	int num = 10; 
	int& ref; // 참조하는 대상이 없으면 오류남.
	ref = num;

참조함수

참조는 포인터와 유사하지만 포인터 문법(->)이 아닌 값복사 문법처럼 간결하게. 을 사용하여 원본데이터에 접근할 수 있다. 그렇기 때문에 값을 읽을 때 주로 사용한다.  함수에서 참조를 매개변수라 하여 사용하면 값 복사인지 참조인지 바로 확인할 수 없다. 보통 값을 읽을 때 사용하기 때문에 참조함수를 사용할 때는 보통 원본데이터를 수정하지 않고 읽기만을 한다는 의미로 참조 매개변수에 const를 입력하여 값을 수정하려는 시도를 막을 수 있다.

 

참조함수 읽기 모드

struct Info
{
	int Id;
	int pwd;
};
int main()
{
	Info info2;
	CreateInfo2(info2);
}
void CreateInfo2(const Info& info)
{
	info.Id = 150;
	info.pwd = 10;
}

참조함수 쓰기 모드

OUT을 사용하여 명시적으로 참조함수에서 변경이 일어남을 표시할 수 있다.

#define OUT

struct Info
{
	int Id;
	int pwd;
};
int main()
{
	Info info2;
	CreateInfo2(info2);
}
void CreateInfo2(OUT Info& info)
{
	info.Id = 150;
	info.pwd = 10;
}

Pointer to 참조와 참조 to Pointer

포인터를 참조로 변경하기 위해서는 *연산자를 사용하여 포인터가 가리키는 데이터를 넣어주면 된다.

참조에서 포인터로 변경하기 위해서는 &연산자를 사용하여 참조의 주소값을 넘겨주면 된다.

struct Info
{
	int Id;
	int pwd;
};
int main()
{
	Info* pointer  = nullptr;
	Info& reference = *pointer;

	PrintInfoByRef(*pointer);
	PrintInfoByPtr(&reference);
}
void PrintInfoByRef(Info& info)
{
	info.Id = 100;
	info.pwd = 100;
}
void PrintInfoByPtr(Info*  info)
{
	info->Id = 150;
	info->pwd = 10;
}

 

 

728x90