C++에서 static 의 용법 을 자세히 설명 합 니 다.

8507 단어 c + +static사용법
C 언어의 static 키 워드 는 세 가지(구체 적 으로 두 가지)용도 가 있다.
1.정적 부분 변수:함수 체 내부 수식 변수 에 사용 되 는데 이런 변수의 생존 기간 은 이 함수 보다 길다.

int foo(){ 
  static int i = 1; // note:1 
  //int i = 1; // note:2 
  i += 1; 
  return i; 
} 
이 용법 을 이해 하려 면,우 리 는 먼저 c/c++의 메모리 분포 와 static 가 있 는 구간 을 이해 해 야 한다.
다음 그림 과 같은 완전한 프로그램 에 대한 메모리 분포 상황:
1.스 택 구역:컴 파일 러 가 자동 으로 분배 하여 방출 합 니 다.예 를 들 어 부분 변수,함수 매개 변 수 는 모두 스 택 구역 에 있 습 니 다.퇴출 작용 에 따라 공간 을 방출 합 니 다.
3.퇴적 구역:프로그래머 가 분배 하고 방출 하 는 구역,예 를 들 어 malloc(c),new(c++)
3.전역 데이터 구역(정적 구역):전역 변수 와 정적 변 령 의 저장 소 는 한 곳 에 놓 여 있 습 니 다.초기 화 된 전역 변수 와 정적 변 수 는 한 지역 에 있 습 니 다.초기 화 되 지 않 은 전역 변수 와 초기 화 되 지 않 은 정적 변 수 는 인접 한 다른 지역 에 있 습 니 다.프로그램 종료 석방.
4.코드 영역
그래서 위의 note:1 의 static 는 전체 데이터 구역 에서 분 배 된 것 입 니 다.그러면 존재 한 다 는 뜻 은 무엇 입 니까?또 언제 초기 화 했 어 요?
먼저 첫 번 째 질문 에 대답 합 니 다.첫 번 째 함수 호출 에 따라 초기 화 되 지만 함수 호출 이 끝나 면 소각 되 지 않 습 니 다.(상기 note:1 을 note:2 로 바 꾸 면 i 는 스 택 에서 분 배 됩 니 다.foo 호출 이 끝나 면 방출 됩 니 다)
그러면 두 번 째 문제 도 수면 위로 떠 올 랐 습 니 다.첫 번 째 호출 이 note:1 에 들 어 갔 을 때 초기 화 되 었 습 니 다.그리고 한 번 만 초기 화 합 니 다.즉,두 번 째 foo()를 호출 합 니 다.계속 초기 화 하지 않 고 바로 건 너 뜁 니 다.
그러면 전체 변 수 를 정의 하 는 것 과 어떤 차이 가 있 습 니까?똑 같이 초기 화 되 고 foo()를 연속 으로 호출 한 결 과 는 같 습 니 다.그러나 전체 변 수 를 사용 하면 변 수 는 함수 자체 에 속 하지 않 습 니 다.함수 의 제어 만 받 지 않 고 프로그램의 유지 에 불편 을 가 져 옵 니 다.
정적 부분 변 수 는 이 문 제 를 해결 할 수 있다.정적 부분 변 수 는 스 택 에 저장 하 는 것 이 아니 라 전체 데이터 영역 에 저 장 됩 니 다.매번 값 은 다음 호출 까지 유지 합 니 다.
그러면 정적 부분 변수의 특징(괄호 안에 note:2,즉 부분 변수의 대비)을 정리 합 니 다.
(1)이 변 수 는 전역 데이터 구역 에서 메모 리 를 분배 합 니 다(국부 변 수 는 창고 구역 에서 메모 리 를 분배 합 니 다).
(2)정적 부분 변 수 는 프로그램 이 이 대상 의 성명 에 실 행 될 때 처음으로 초기 화 됩 니 다.즉,이후 의 함수 호출 은 초기 화 되 지 않 습 니 다(부분 변 수 는 함수 호출 때마다 초기 화 됩 니 다).
(3)정적 부분 변 수 는 일반적으로 성명 에서 초기 화 됩 니 다.명시 적 으로 초기 화 되 지 않 으 면 프로그램 에서 0 으로 자동 으로 초기 화 됩 니 다(부분 변 수 는 초기 화 되 지 않 습 니 다).
(4)프로그램 이 실 행 될 때 까지 전역 데이터 구역 에 머 물 러 있 습 니 다.그러나 그 역할 영역 은 부분 적 인 역할 영역 입 니 다.즉,함수 체 밖에서 사용 할 수 없습니다(부분 변 수 는 스 택 구역 에 있 고 함수 가 끝 난 후에 바로 메모 리 를 방출 합 니 다).
2.정적 전역 변수:함수 체 외 에 정의 되 어 전역 변 수 를 수식 하 는 데 사용 되 며 이 변 수 는 이 파일 에서 만 볼 수 있 음 을 나타 낸다.

static int i = 1; //note:3 
//int i = 1; //note:4 
int foo() 
{ 
  i += 1; 
  return i; 
} 
note:3 과 note:4 는 어떤 차이 가 있 습 니까?네가 foo()를 호출 하면 몇 번 을 호출 하 든 그들의 결 과 는 똑같다.즉,이 파일 에서 그들 을 호출 하 는 것 은 완전히 같다 는 것 이다.그렇다면 이들 의 차 이 는 무엇 일 까?
파일 격 리!
만약 에 제 가 a.c 파일 이 있다 고 가정 하면 우 리 는 b.c 를 다시 만 듭 니 다.내용 은 다음 과 같 습 니 다.

//file a.c 
//static int n = 15; //note:5 
int n = 15; //note:6 
//file b.c 
#include <stdio.h> 
extern int n; 
void fn() 
{ 
  n++; 
  printf("after: %d
",n); } void main() { printf("before: %d
",n); fn(); }
우 리 는 먼저 note:6,즉 비 정적 전역 변 수 를 사용 하여 출력 을 다음 과 같이 발견 합 니 다.
before: 15
after: 16
즉,우리 의 b.c 는 extern 을 통 해 a.c 가 정의 하 는 전역 변 수 를 사 용 했 습 니 다.
그러면 우 리 는 note:5,즉 정적 전역 변 수 를 사용 하 는 것 으로 바 꿉 니까?gcc a.c b.c -o output.outundeference to"n"과 같은 오류 가 발생 할 수 있 습 니 다.n 을 찾 을 수 없습니다.static 에서 파일 격 리 를 했 기 때문에 a.c 가 정의 하 는 정적 전역 변 수 를 방문 할 수 없습니다.물론\#include"a.c"를 사용 하면 다 릅 니 다.
이상 에서 우 리 는 정적 전역 변수의 특징 을 얻 을 수 있다.
정적 전역 변 수 는 다른 파일 에 사용 할 수 없습니다(전역 변 수 는 가능 합 니 다).
다른 파일 에 서 는 같은 이름 의 변 수 를 정의 할 수 있 습 니 다.충돌 하지 않 습 니 다.
3.정적 함수:정확히 말 하면 정적 함 수 는 정적 전역 변수의 역할 과 유사 합 니 다.

//file a.c 
#include <stdio.h> 
void fn() 
{ 
  printf("this is non-static func in a"); 
} 
//file b.c 
#include <stdio.h> 
extern void fn(); //   extern       fn(),      。 
void main() 
{ 
  fn(); 
} 
정상적으로 출력 가능:this is non-static func in a.
void fn()에 static 키 워드 를 추가 하면?undefined reference to "fn".
그래서 정적 함수 의 장점 은 정적 전역 변수의 장점 과 유사 하 다.
1.정적 함 수 는 다른 파일 에 사용 할 수 없습니다.
2.다른 파일 에서 같은 이름 의 함 수 를 정의 할 수 있 으 며 충돌 이 발생 하지 않 습 니 다.
위 에서 모두 세 가지 용법 을 말 했 는데,왜 정확히 말 하면 두 가지 입 니까?
1.하 나 는 수식 변수 이 고 하 나 는 수식 함수 이기 때문에 두 가지(이런 해석 은 많 지 않다).
2.정적 전역 변 수 는 정적 함 수 를 수식 하 는 역할 과 같 고 보통 하나 로 합 친다.(이것 은 비교적 많은 분 법 이다.
C++언어의 static 키 워드 는 두 가지 용도 가 있 습 니 다.
물론 이상 의 몇 가지 도 c++에 사용 할 수 있 습 니 다.그리고 추가 적 인 두 가지 용법 이 있다.
1.정적 데이터 구성원:class 의 데이터 구성원,즉'정적 구성원'을 수식 하 는 데 사 용 됩 니 다.이러한 데이터 구성원 의 생존 기간 은 class 의 대상(실체 instance)보다 크다.정적 데이터 구성원 은 모든 class 에 한 부 씩 있 고 일반 데이터 구성원 은 모든 intance 에 한 부 씩 있 기 때문에 정적 데이터 구성원 도 클래스 변수 라 고 부 르 고 일반 데이터 구성원 도 인 스 턴 스 변수 라 고 부른다.

#include<iostream> 
using namespace std; 
class Rectangle 
{ 
private: 
  int m_w,m_h; 
  static int s_sum; 
public: 
  Rectangle(int w,int h) 
  { 
    this->m_w = w; 
    this->m_h = h; 
    s_sum += (this->m_w * this->m_h); 
  } 
  void GetSum() 
  { 
    cout<<"sum = "<<s_sum<<endl; 
  } 
}; 
int Rectangle::s_sum = 0; //    
int main() 
{ 
  cout<<"sizeof(Rectangle)="<<sizeof(Rectangle)<<endl; 
  Rectangle *rect1 = new Rectangle(3,4); 
  rect1->GetSum(); 
  cout<<"sizeof(rect1)="<<sizeof(*rect1)<<endl; 
  Rectangle rect2(2,3); 
  rect2.GetSum(); 
  cout<<"sizeof(rect2)="<<sizeof(rect2)<<endl; 
  system("pause"); 
  return 0; 
} 
결 과 는 다음 과 같다.

그림 에서 알 수 있 듯 이sizeof(Rectangle)=8bytes=sizeof(m_w)+sizeof(m_h)즉,static 는 Rectangle 의 메모리 공간 을 차지 하지 않 는 다.
그럼 static 은 어디에서 메모 리 를 분배 합 니까?예,전역 데이터 영역(정적 영역)입 니 다.
겟 섬(GetSum)을 살 펴 보면 1 차 12=3*4,2 차 18=12+2*3 이다.이 를 통 해 static 는 인 스 턴 스 와 무관 하 게 한 번 만 초기 화 될 수 있 습 니 다.
결론:
비정 상 데이터 구성원 에 대해 서 는 각 유형의 대상(인 스 턴 스)이 자신의 복사 본 을 가지 고 있 습 니 다.정적 데이터 구성원 은 클래스 의 구성원 으로 여 겨 지고 이 유형의 모든 대상 이 공유 하여 접근 합 니 다.이 클래스 의 여러 대상 에 게 정적 데이터 구성원 은 한 번 의 메모리 만 할당 합 니 다.
정적 데이터 구성원 은 전역 데이터 영역 에 저 장 됩 니 다.정적 데이터 구성원 이 정의 할 때 공간 을 분배 해 야 하기 때문에 클래스 성명 에서 정의 할 수 없습니다.
즉,당신 의 모든 new Rectangle 은 static int s 가 아 닙 니 다.sum 의 메모리 복사 본 구축 은 new 가 얼마나 많은 Rectangle 의 인 스 턴 스 를 가지 고 있 든 지 간 에 Rectangle 과 연결 되 어 있 을 뿐 모든 Rectangle 의 대상 과 관계 가 없 기 때 문 입 니 다.
2.정적 구성원 함수:class 를 수식 하 는 구성원 함수 입 니 다.
우 리 는 위의 예 를 약간 바 꾸 었 다.

#include<iostream> 
using namespace std; 
class Rectangle 
{ 
private: 
  int m_w,m_h; 
  static int s_sum; 
public: 
  Rectangle(int w,int h) 
  { 
    this->m_w = w; 
    this->m_h = h; 
    s_sum += (this->m_w * this->m_h); 
  } 
  static void GetSum() //    static 
  { 
    cout<<"sum = "<<s_sum<<endl; 
  } 
}; 
int Rectangle::s_sum = 0; //    
int main() 
{ 
  cout<<"sizeof(Rectangle)="<<sizeof(Rectangle)<<endl; 
  Rectangle *rect1 = new Rectangle(3,4); 
  rect1->GetSum(); 
  cout<<"sizeof(rect1)="<<sizeof(*rect1)<<endl; 
  Rectangle rect2(2,3); 
  rect2.GetSum(); //      .      
  cout<<"sizeof(rect2)="<<sizeof(rect2)<<endl; 
  Rectangle::GetSum(); //        ::      
  system("pause"); 
  return 0; 
} 
위의 설명 을 보면 GetSum()에 static 을 추가 하여 정적 구성원 함수 로 만 들 고 클래스 이름:함수 이름 으로 접근 할 수 있 습 니 다.
그럼 정적 멤버 함수 가 특징 이 있 나 요?
1.정적 구성원 간 에 서로 접근 할 수 있 습 니 다.정적 구성원 함수 가 정적 데이터 구성원 에 접근 하고 정적 구성원 함수 에 접근 하 는 것 을 포함 합 니 다.
2.비 정적 구성원 함 수 는 정적 구성원 함수 와 정적 데이터 구성원 을 임의로 방문 할 수 있 습 니 다.
3.정적 구성원 함 수 는 비정 상 구성원 함수 와 비정 상 데이터 구성원 에 접근 할 수 없습니다.
4.정적 구성원 함 수 를 호출 합 니 다.구성원 접근 연산 자(.)와(->)를 같은 유형의 대상 이나 클래스 대상 을 가리 키 는 포인터 로 정적 구성원 함 수 를 호출 할 수도 있 습 니 다.클래스 이름 으로 호출 할 수도 있 습 니 다.함수 이름 으로 호출 할 수도 있 습 니 다.(원래 클래스 에 속 하기 때문에 클래스 이름 으로 호출 하 는 것 이 정상 입 니 다)
앞의 세 가 지 는 사실 한 가지 입 니 다.정적 구성원 함 수 는 비정 상(구성원 함수 와 데이터 구성원 포함)에 접근 할 수 없 지만 비정 상 은 정적 에 접근 할 수 있 습 니 다.좀 어 지 럽 습 니까?괜 찮 습 니 다.제 가 설명 하 겠 습 니 다.정적 은 클래스 에 속 하기 때문에 10 개 를 만 들 었 는 지 100 개 를 만 들 었 는 지 모 르 기 때문에 대상 의 함수 나 데이터 에 대해 아무것도 모 르 기 때문에 호출 할 수 없습니다.반대로 당신 이 만 든 대상 은 클래스 에 대해 명확 합 니 다.(그렇지 않 으 면 당신 은 어떻게 그것 에서 예화 합 니까?)그래서 클래스 함수 와 클래스 구성원 을 호출 할 수 있 습 니 다.GetSum 이 static 이 든 아니 든 static 의 s 를 호출 할 수 있 습 니 다.sum 은 같다.

좋은 웹페이지 즐겨찾기