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.out
undeference 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 은 같다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
hdu 1717 소수 화 점수 2 (수학)소수 화 점수 2 레이 는 수학 시간 에 선생님 의 말씀 을 듣 고 모든 소수 가 점수 로 표시 되 는 형식 이 라 고 말 했다. 그 는 녹 기 시 작 했 고 곧 완성 되 었 다. 그러나 그 는 또 하나의 문 제 를...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.