c++ - 헤더 - 유니티 전역 변수




인라인 함수의 정적 변수 (6)

Static은 프로그램 전체에 하나의 사본이 배포되지만 인라인이란 동일한 프로그램에서 여러 번 동일한 코드가 필요하다는 것을 의미하므로 인라인 함수 내에서 변수를 정적으로 만들 수는 없습니다.

헤더 파일에 선언되고 정의 된 함수가 있습니다. 이것은 모두 자체적으로 문제입니다. 그 함수가 인라인되지 않을 때, 그 헤더를 사용하는 모든 번역 단위는 그 함수의 복사본을 얻게되고, 그것들이 함께 링크 될 때 그 사본이 복사됩니다. 함수를 인라인으로 만들어서 고정 시켰지만, "인라인"키워드를 지정해도 컴파일러가 인라인을 보장하지 못하기 때문에 이것은 매우 약한 솔루션이라고 우려합니다. 이것이 사실이 아니라면, 저를 시정하십시오.

어쨌든, 진짜 질문은,이 함수 내부의 정적 변수는 어떻게 될까요? 얼마나 많은 사본이 나옵니까?


그것은 이런 식으로되어 있습니다. "정적"은 컴파일러에게 함수가 컴파일 단위에 로컬이되기를 원하므로 컴파일 단위 당 하나의 복사본과 함수 인스턴스 당 정적 변수의 복사본 하나를 원합니다.

"인라인"은 컴파일러에게 함수가 인라인되기를 원할 때 사용된다; 요즘에는 코드의 사본이 여러 개 있으면 "그냥 같은 기능인지 확인하십시오."라는 메시지가 표시됩니다. 그래서 모든 사람들이 정적 변수를 공유합니다.

참고 :이 답변은 원래 포스터가 자신에게 올린 답변에 대한 응답으로 작성되었습니다.


나는 컴파일러가 변수의 많은 복사본을 생성한다고 생각하지만, 링커는 하나를 선택하여 다른 모든 참조를 참조하게한다. 다른 버전의 인라인 함수를 만들기 위해 실험을 시도했을 때 비슷한 결과를 얻었습니다. 함수가 실제로 인라인되지 않은 경우 (디버그 모드) 호출 된 소스 파일에 관계없이 모든 함수가 동일한 함수로 이동합니다.

컴파일러가 잠시 동안 생각해보십시오. 그렇지 않으면 어떻게 될까요? 각 컴파일 단위 (소스 파일)는 다른 컴파일 단위와 독립적이며 별도로 컴파일 할 수 있습니다. 그러므로 각 변수는 유일한 변수라고 생각하면서 변수의 복사본을 만들어야합니다. 링커는 해당 경계를 넘어서서 변수와 함수 모두에 대한 참조를 조정할 수 있습니다.


네가 뭔가를 놓친 것 같아.

정적 함수?

정적 함수를 선언하면 해당 컴파일 단위에서 "숨김"상태가됩니다.

이름 공간 범위 (3.3.6)를 갖는 이름은 그것이 이름 인 경우 내부 연결을 갖는다.

- 명시 적으로 정적이라고 선언 된 변수, 함수 또는 함수 템플릿.

3.5 / 3 - C ++ 14 (n3797)

이름에 내부 연결이 있으면이 연결이 나타내는 엔티티는 동일한 번역 단위의 다른 범위에있는 이름으로 참조 될 수 있습니다.

3.5 / 2 - C ++ 14 (n3797)

이 정적 함수를 헤더에 선언하면이 헤더를 포함하는 모든 컴파일 단위에 해당 함수의 복사본이 생깁니다.

문제는 함수 내에 정적 변수가있는 경우이 헤더를 포함하는 각 컴파일 단위에도 자체적 인 개인 버전이 있다는 것입니다.

인라인 함수?

인라인으로 선언하면 컴파일러가 인라인 여부에 관계없이 인라인 (inline)을위한 후보가됩니다 (현재 인라인 키워드가 존재하거나 존재하지 않는다는 사실을 무시할 때 C ++에서는 요즘 많이 쓰이는 것은 아닙니다).

인라인 지정자가있는 함수 선언 (8.3.5, 9.3, 11.3)은 인라인 함수를 선언합니다. 인라인 지정자는 호출 시점에서 함수 본문의 인라인 대체가 일반적인 함수 호출 메커니즘보다 선호된다는 것을 구현에 나타냅니다. 구현시 호출 지점에서이 인라인 대체를 수행 할 필요가 없습니다. 그러나이 인라인 대체가 생략 되더라도 7.1.2에 정의 된 인라인 함수의 다른 규칙은 여전히 ​​존중되어야합니다.

7.1.2 / 2 - C ++ 14 (n3797)

헤더에는 흥미로운 부작용이 있습니다. 인라인 함수는 동일한 모듈에서 여러 번 정의 될 수 있으며 링커는 컴파일러의 이유로 인라인되지 않으면 단순히 "그들"을 하나로 결합합니다.

안쪽에 선언 된 정적 변수의 경우, 표준에서 구체적으로 그 중 하나만 나타내며 그 중 하나만 나타냅니다.

extern 인라인 함수의 정적 로컬 변수는 항상 동일한 객체를 참조합니다.

7.1.2 / 4 - C ++ 98 / C ++ 14 (n3797)

(함수는 기본적으로 extern이므로 함수를 정적으로 표시하지 않는 한 해당 함수에 적용됩니다)

이것은 결함이없는 "정적"(즉 헤더에 정의 될 수 있음)의 이점이 있습니다 (인라인되지 않으면 한 번 존재합니다)

정적 지역 변수?

정적 지역 변수는 연결이 없습니다 (범위 외부에서 이름으로 참조 할 수는 없지만 정적 저장 기간이 있습니다 (즉, 전역이지만 구성 및 파괴는 특정 규칙을 따릅니다).

정적 + 인라인?

인라인과 정적을 혼합하면 설명 된 결과를 얻을 수 있습니다 (함수가 인라인 되어도 내부의 정적 변수는 존재하지 않더라도 정적 함수의 정의를 포함하여 컴파일 단위만큼 많은 정적 변수로 끝납니다) ).

작성자의 추가 질문에 대한 답변

필자가 Visual Studio 2008을 사용해 보았던 질문을 쓴 이후로 VS가 표준을 준수하도록하는 모든 옵션을 설정하려고 시도했지만 일부는 놓친 것일 수 있습니다. 결과는 다음과 같습니다.

함수가 단순히 "인라인"일 경우 정적 변수의 복사본은 하나뿐입니다.

함수가 "정적 인라인"인 경우 번역 단위만큼 사본이 있습니다.

진짜 문제는 지금 상황이 이런 식으로되어 있는지, 아니면 이것이 Microsoft C ++ 컴파일러의 특질인지 여부입니다.

그래서 나는 당신이 그런 것을 가지고 있다고 생각합니다 :

void doSomething()
{
   static int value ;
}

함수의 정적 변수는 함수의 범위를 제외한 모든 변수에 숨겨진 전역 변수를 넣으면됩니다. 즉, 내부에서 선언 된 함수 만 도달 할 수 있습니다.

함수를 인라인하면 아무 것도 바뀌지 않습니다 :

inline void doSomething()
{
   static int value ;
}

단 하나의 숨겨진 전역 변수가 있습니다. 컴파일러가 코드를 인라인하려고 시도하더라도 사실은 하나의 전역 숨겨진 변수 만 변경되지는 않습니다.

이제 함수가 정적으로 선언 된 경우 :

static void doSomething()
{
   static int value ;
}

정적 함수가 선언 된 헤더를 포함하는 모든 CPP 파일에는 전역 숨김 변수의 자체 복사본을 포함하여 함수의 자체 복사본이 있으므로 모든 컴파일 단위에 대해 "개인"이므로 많은 변수가 있습니다. 헤더를 포함한 컴파일 단위가 있습니다.

내부에 "정적"변수가있는 "정적"함수에 "인라인"추가 :

inline static void doSomething()
{
   static int value ;
}

안쪽의 정적 변수에 관한 한,이 "인라인"키워드를 추가하지 않은 것과 같은 결과가 나타납니다.

따라서 VC ++의 동작은 정확하며 "인라인"및 "정적"의 실제 의미를 착각하고 있습니다.


인라이닝은 실행 가능한 코드 (명령어)가 호출하는 함수의 코드에 인라인된다는 것을 의미합니다. 컴파일러는 요청 여부와 관계없이이를 수행 할 수 있습니다. 함수에서 선언 된 변수 (데이터)에는 아무런 영향을 미치지 않습니다.


필자가 Visual Studio 2008을 사용해 보았던 질문을 쓴 이후로 VS가 표준을 준수하도록하는 모든 옵션을 설정하려고 시도했지만 일부는 놓친 것일 수 있습니다. 결과는 다음과 같습니다.

함수가 단순히 "인라인"일 경우 정적 변수의 복사본은 하나뿐입니다.

함수가 "정적 인라인"인 경우 번역 단위만큼 사본이 있습니다.

진짜 문제는 지금 상황이 이런 식으로되어 있는지, 아니면 이것이 Microsoft C ++ 컴파일러의 이데노시즘인지 여부입니다.





inline-functions