인 스 턴 스 는 C+에서 포인터 와 참조 의 차 이 를 자세히 설명 합 니 다.

머리말
컴퓨터 에 데 이 터 를 저장 할 때 반드시 세 가지 기본 요 소 를 알 아야 한다.정 보 는 어디 에 저장 되 어 있 습 니까?저 장 된 값 은 얼마 입 니까?저 장 된 값 은 어떤 유형 입 니까?따라서 지침 은 정보 가 메모리 에 주 소 를 저장 하 는 특수 한 변수 로 지침 과 그 가 가리 키 는 변 수 는 동전 의 양면 과 같다.지침 은 C 언어 를 배 우 는 데 어려움 을 겪 었 고 C++에 인용 개념 이 하나 더 생 겼 다.초학 때 이 두 개념 을 헷 갈 리 기 쉬 우 니 다음은 몇 가지 예 를 통 해 양자 간 의 차 이 를 설명 한다.
1.지침 의 성명
위 에서 언급 한 바 와 같이 포인터 와 그 가 가리 키 는 변 수 는 동전 의 양면 과 같 기 때문에 주소 기호'&'를 통 해 변수의 주 소 를 찾 을 수 있 고 인용 기호'*'를 풀 면 주소 에 저 장 된 변수 값 을 찾 을 수 있다.

int data = 10; //       data,     10,     int  
int* p_data = &data; //   data          , p_data
cout << "   :" << int(p_data) << "\t      :" << data << endl;
출력 결 과 는:
주소:8191436  저장 한 값:10
주 소 는 기본적으로 16 진법 입 니 다.출력 할 때 int 형식 으로 변환 되 었 기 때문에 10 진법 으로 출력 합 니 다.출력 결 과 를 번역 하면 주소 인 코딩 이 8191436 인 위치 에 10 인 변수 data 를 저장 하고 더 나 아가 data 와*pdata 는 같은 것 을 나타 낸다.이해 에 도움 이 되도록 다음 그림 을 그 렸 습 니 다.

따라서 본질 적 으로 포인터 와 일반적인 변 수 는 큰 차이 가 없 으 며 포인터 변 수 는 인용 을 푸 는 방식 으로 포인터 에 해당 하 는 주소 에 저 장 된 수 치 를 찾 을 수 있 습 니 다.다음 과 같이 정의 한다 면:

int data = 10;
int* p_data = &data;  //     int       p_data,      int       data   , 
int** p_p_data = &p_data; //     int*       p_p_data,      int*       p_data   

cout << "p_data:" << p_data << "\t      :" << *p_data << endl;
cout << "p_p_data:" << p_p_data << "\t      :" << *p_p_data << endl;

출력 결 과 는:
p_data:00EFF96C         저장 한 값:10
p_p_data:00EFF960       저 장 된 값:00EFF96C
출력 결과 에서 보 듯 이 pp_data 에 저 장 된 값 은 pdata,그리고 pdata 에 저 장 된 값 은 바로 data 입 니 다.'사랑 해,사랑 해'와 같은 브리지 입 니 다.다음은 변수 와 포인터 간 의 관 계 를 중점적으로 분석 합 니 다.우 리 는 상기 예 에서 포인터 를 변수의 주소 로 초기 화 합 니 다.변 수 는 컴 파일 할 때 분 배 된 이름 이 있 는 메모리 입 니 다.포인 터 는 이름 을 통 해 직접 접근 할 수 있 는 메모리 에 만 개별 이름 을 제공 합 니 다.또한 위의 예 를 들 어 프로그래머 에 게 변수 10 의 이름 은 data 이다.컴퓨터 에 있어 변수 10 은 8191436 주소 가 존재 하 는 데이터 이다.프로그래머 와 컴퓨터 의 소통 을 실현 하 는 방식 은 바로 지침 이다.data 주소 지정 을 통 해 프로그래머 가 컴퓨터 의 저장 구 조 를 이해 할 수 있 도록 하 는 것 이다.마찬가지 로 주소 에 대한 인용 을 통 해 이 주소 에 저 장 된 데 이 터 를 쉽게 찾 을 수 있다.위 와 같은 상황 에서 포인터 의 출현 은 다소 불필요 해 보이 지만 포인터 의 진정한 용 도 는 실행 단계 에서 이름 이 없 는 메모 리 를 저장 값 으로 분배 하 는 것 이다.이런 상황 에서 포인터 로 만 메모리 에 접근 할 수 있다.
마지막 으로 포인터 성명 에 대한 조언:포인터 변 수 를 설명 할 때 정확 한 주 소 를 지정 해 야 합 니 다.그렇지 않 으 면 성명 의 포인터 변 수 는 어디 를 가리 키 는 지 모 르 기 때문에 시스템 붕 괴 를 초래 하기 쉽 습 니 다.
2、new 를 사용 하여 메모리 할당
메모리 4 구역 의 코드 구역,전역 구역,창고 구역 과 더미 구역 에서 언급 한 적 이 있 습 니 다.new 는 더미 구역 에 메모리 공간 을 만 듭 니 다.반환 값 은 이 메모리 공간의 주소 입 니 다.따라서 프로그래머 의 책임 은 이 주 소 를 포인터 에 부여 하 는 것 입 니 다.다음은 예시 입 니 다.

int* p_data = new int; //         ,           
*p_data = 10; //          10
cout << "p_data:\t" << p_data << "\t *p_data: " << *p_data << endl;
비 교 를 통 해 new 뒤에 데이터 형식 int 를 지정 하 였 습 니 다.마찬가지 로 pdata 도 int 를 가리 키 는 지침 으로 밝 혀 졌 다.이 는 컴퓨터 의 메모리 가 바이트 단위 로 되 어 있 기 때문에 서로 다른 유형의 변 수 는 서로 다른 바이트 를 차지 하기 때문에 new 를 사용 할 때 컴 파일 러 에 몇 바이트 의 저장 공간 을 분배 하 는 지 알려 야 하고 받 은 지침 도 성명 의 유형 과 일치 해 야 하기 때문이다.출력 결 과 는:
p_data: 00D0D9A0         *p_data: 10
대형 데 이 터 를 처리 할 때,예 를 들 어 배열 을 처리 할 때 일반적으로 사용 하 는 방법 은 하나의 배열 형식의 데 이 터 를 정의 하고 정의 할 때 충분 한 공간 을 분배 하 는 것 이다.그러나 이 방법 은 너무 딱딱 하지만 new 를 사용 할 때 실행 단계 에 배열 이 필요 하 다 면 만 듭 니 다.필요 하지 않 으 면 만 들 지 않 습 니 다.가장 중요 한 것 은 프로그램 이 실 행 될 때 배열 의 길 이 를 선택 하 는 것 입 니 다.동적 배열 을 만 들 기 위해 new 를 사용 하 는 방법 을 살 펴 보 겠 습 니 다.C++에서 배열 이름 은 배열 주소,즉 배열 의 첫 번 째 요소 의 주소 로 해 석 됩 니 다.다음은 실례 입 니 다.

int Arr[10]; //       10 int       
cout << "Arr:" << Arr << "\t&Arr[0]:" << &Arr[0] <<endl;
출력 결 과 는:
Arr:008FFAB4    &Arr[0]:008FFAB4
이러한 성명 방식 은 처음부터 고정된 배열 의 길 이 를 설명 할 수 있 습 니 다.C++에서 동적 배열 을 만 들 때 배열 의 요소 유형 과 요소 수 를 new 에 게 만 알려 주면 됩 니 다.new 의 반환 값 은 같은 배열 의 첫 번 째 주소 입 니 다.

int ele_num = 10; //            
int* p_arr = new int [ele_num]; //               
new 를 통 해 쌓 인 공간 을 열 고 프로그래머 가 관리 하여 방출 합 니 다.따라서 new 메모리 가 사용 되 지 않 으 면 delete 를 통 해 변 수 를 만 들 고 delete[]를 사용 하여 열 린 배열 공간 을 방출 해 야 합 니 다.코드 는 다음 과 같 습 니 다:

int* p_data = new int;
*p_data = 10;
cout << "p_data: " << p_data << "\t*p_data:" << *p_data << endl;

int ele_num = 10;
int* p_arr = new int [ele_num];

for(int i = 0; i<9; i++)
 *(p_arr+i) = i+2;

cout << "p_arr:" << p_arr << "\t\t*(p_array):";
for(int i = 0; i<9; i++)
 cout << *(p_arr + i) << " ";
cout << endl;

delete p_data;
delete [] p_arr;

cout << "
****** delete ......*******" << endl; cout << "p_data: " << p_data << "\t*p_data:" << *p_data << endl; cout << "p_arr:" << p_arr << "\t\t*(p_array):"; for(int i = 0; i<9; i++) cout << *(p_arr + i) << " "; cout << endl;
출력 결 과 는 다음 과 같 습 니 다.
p_data: 0082B1C8        *p_data:10
p_arr:0082BB58          *(p_array):2 3 4 5 6 7 8 9 10
*****delete 메모리 사용 후...*********
p_data: 0082B1C8        *p_data:-572662307
p_arr:0082BB58          *(p_array):-572662307 -572662307 -572662307 -572662307 -572662307 -572662307 -572662307 -572662307 -572662307
3.malloc 와 new 의 차이
C 언어 를 배 운 친구 들 은 모두 알 고 있 습 니 다.C 언어 에서 malloc 함 수 를 통 해 메모리 공간 을 열 었 습 니 다.malloc 의 함수 원형 은 다음 과 같 습 니 다.

void* malloc(unsigned int numbytes);
함수 원형 의 매개 변 수 를 통 해 알 수 있 듯 이 malloc 함 수 는 바이트 수 를 매개 변수 로 하여 고정 바이트 의 메모리 공간 을 엽 니 다.이것 은 new 와 첫 번 째 차이 가 있 습 니 다.new 는 바이트 수 를 스스로 계산 할 필요 가 없습니다.메모리 에 저 장 된 데이터 형식 과 메타 수 만 지정 하면 됩 니 다.
함수 원형 의 반환 유형 을 통 해 알 수 있 듯 이 malloc 함 수 는 void*형식 으로 되 돌아 갑 니 다.사용 할 때 포인터 형식 을 지정 해 야 합 니 다.예 를 들 면:

int* p_malloc = nullptr; //       int   
p_malloc = (int*) malloc(10); //  malloc           int*   
new 는 사용 할 때 필요 하지 않 습 니 다.요약 하면 malloc 는 사용 할 때 메모리 의 데이터 형식 과 메모리 길이 에 따라 처 에 필요 한 바이트 수 를 계산 한 다음 에 void*형식 으로 돌아 가 대응 하 는 형식의 지침 을 사용 하여 수신 해 야 합 니 다.new 는 사용 할 때 메모리 의 길이 와 메모리 의 데이터 형식 만 지정 하면 컴 파일 러 는 필요 한 바이트 수 를 자동 으로 계산 합 니 다.
4.인용 한 성명 과 본질
C++에 정 의 된 변 수 를 참조 하 는 별명 이 추가 되 었 습 니 다.인용 의 가장 주요 한 용 도 는 함수 형 삼 이다.이렇게 하면 함 수 는 데이터 복사 본 이 아니 라 원시 데 이 터 를 사용 할 수 있다.이렇게 들 으 면 지침 과 다 를 것 이 없 는 것 같다.우 리 는 인용 한 성명 부터 말 하 자.

int data = 10;
int& p_data = data; //         p_data
cout << "data:" << data << "\tp_data:" << p_data << endl; //p_data   data             
출력 결 과 는:
data:10  p_data:10
출력 결 과 를 보면 pdata 와 data 는 하나의 변수의 두 가지 다른 명칭 일 뿐이다.인용 은 성명 할 때 초기 값 을 지정 해 야 하 며 포인터 처럼 먼저 설명 하고 값 을 부여 할 수 없습니다.다음은 함수 로 서 의 매개 변 수 를 인용 하여 인용 과 지침 의 차 이 를 설명 합 니 다.

template <typename T> //        
void swap(T a, T b){
 int temp;
 temp = a;
 a = b;
 b = temp;
}
int main(void){
 int a = 10, b = 20; 
 swap_value<int>(a,b); //       
 cout << "a:" << a << "\t\tb:" << b << endl;
 swap_value<int&>(a,b); //        
 cout << "
a:" << a << "\t\tb:" << b << endl; }
상기 코드 에서 볼 수 있 듯 이 값 전달 과 인용 전달 의 형 삼 은 모두 같 습 니 다.다른 것 은 인용 전달 일 때 실제 인삼 은 인용 으로 설명 되 고 인용 하 는 용법 은 사용 값 과 똑 같 습 니 다.출력 결 과 는 다음 과 같 습 니 다.
a:10            b:20
a:20            b:10
놀랍게도 인용 전달 이 원시 데이터 의 값 을 바 꾸 었 다 는 것 은 지침 의 용법 과 일치 하지만 지침 은 swap 함 수 를 쓸 때 이렇게 써 야 한다.

void swap(int* a, int* b){
 int temp;
 temp = *a;
 *a = *b;
 *b = temp;
}
swap(&a, &b); //    
종합 적 으로 보면 인용 은 변수의 또 다른 이름 으로 그 용법 은 변수 와 똑 같 지만 형 삼 으로 전 달 될 때 원시 데이터 의 값 을 바 꿀 수 있다.이러한 용법 상의 차 이 를 제외 하고 인용 의 본질은 바로 하나의 지침 상수 로 지침 이 가리 키 는 위 치 는 변 할 수 없 지만 지침 이 위 치 를 가리 키 는 값 은 변 할 수 있다 는 것 을 의미한다.즉:

//           ,              
int& p_a = a;  
int* const p_a=&a;
조금 만 더 작은 지식 을 보충 하면 const 수식 부 에 관 한 문제 에 대해 어떤 초보 친구 들 은 const 가 무엇 을 가 변 적 이 고 무엇 을 가 변 적 이지 않 은 것 인지 알 지 못 하기 쉽다.구체 적 인 실례 는 다음 과 같다.

int data = 10, data2 = 20;
const int* p_data = &data; //    int,  p_data         , p_data  
p_data = &data2;

int* const p_data2 = &data; //    int*,  p_data        , p_data   
*p_data2 = data2;

인용 은 두 번 째 용법 이다.
총결산
C++에서 포인터 와 인용의 차이 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 C++포인터 와 인용 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 부탁드립니다!

좋은 웹페이지 즐겨찾기