Programing

인라인 함수의 정적 변수

lottogame 2020. 10. 24. 09:22
반응형

인라인 함수의 정적 변수


헤더 파일에 선언되고 정의 된 함수가 있습니다. 이것은 그 자체로 문제입니다. 해당 함수가 인라인되지 않으면 해당 헤더를 사용하는 모든 번역 단위가 함수의 복사본을 가져오고 함께 연결될 때 중복됩니다. 함수를 인라인으로 만들어서 "고정"했지만, 내가 아는 한 "inline"키워드를 지정하더라도 컴파일러가 인라인을 보장하지 않기 때문에 이것이 깨지기 쉬운 솔루션이라는 것이 두렵습니다. 이것이 사실이 아닌 경우 저를 수정하십시오.

어쨌든 진짜 질문은이 함수 내부의 정적 변수는 어떻게 되나요? 몇 개의 사본으로 끝나나요?


여기에 뭔가 빠진 것 같아요.

정적 기능?

함수를 static으로 선언하면 컴파일 단위에서 "숨겨집니다".

네임 스페이스 범위 (3.3.6)가있는 이름은 다음과 같은 경우 내부 연결이 있습니다.

— 명시 적으로 정적으로 선언 된 변수, 함수 또는 함수 템플릿

3.5 / 3-C ++ 14 (n3797)

이름에 내부 연결이있는 경우 해당 엔터티는 동일한 번역 단위에있는 다른 범위의 이름으로 참조 될 수 있습니다.

3.5 / 2-C ++ 14 (n3797)

이 정적 함수를 헤더에 선언하면이 헤더를 포함한 모든 컴파일 단위에 자체 함수 사본이 있습니다.

문제는 해당 함수 내에 정적 변수가있는 경우이 헤더를 포함하는 각 컴파일 단위도 고유 한 개인 버전을 갖게됩니다.

인라인 기능?

인라인으로 선언하면 인라인 후보가됩니다 (요즘 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 파일에는 전역 숨겨진 변수의 자체 사본을 포함하여 함수의 자체 사본이 있으므로 다음과 같은 많은 변수가 있습니다. 헤더를 포함한 컴파일 단위가 있습니다.

Adding "inline" to a "static" function with a "static" variable inside:

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

has the same result than not adding this "inline" keyword, as far as the static variable inside is concerned.

So the behaviour of VC++ is correct, and you are mistaking the real meaning of "inline" and "static".


I believe the compiler creates many copies of the variable, but the linker picks one and makes all the others reference it. I had similar results when I tried an experiment to create different versions of an inline function; if the function wasn't actually inlined (debug mode), all calls went to the same function regardless of the source file they were called from.

Think like a compiler for a moment - how could it be otherwise? Each compilation unit (source file) is independent of the others, and can be compiled separately; each one must therefore create a copy of the variable, thinking it is the only one. The linker has the ability to reach across those boundaries and adjust the references for both variables and functions.


I found Mark Ransom's answer helpful - that the compiler creates many copies of the static variable, but the linker chooses one and enforces it across all translation units.

Elsewhere I found this:

See [dcl.fct.spec]/4

[..] An inline function with external linkage shall have the same address in all translation units. A static local variable in an extern inline function always refers to the same object. A string literal in an extern inline function is the same object in different translation units.

I don't have a copy of the standard to check, but it matches with my experience examining the assembly in VS Express 2008


It is supposed to be this way. "static" tells the compiler you want the function to be local to the compilation unit, therefore you want one copy per compilation unit and one copy of the static variables per instance of the function.

"inline" used to tell the compiler you want the function to be inlined; nowadays, it just takes it as "it's ok if there are several copies of the code, just make sure it's the same function". So everybody shares the static variables.

Note: this answer was written in response to the answer the original poster posted to himself.


Since I wrote the question I tried it out with Visual Studio 2008. I tried to turn on all the options that make VS act in compliance with standards, but it's possible that I missed some. These are the results:

When the function is merely "inline", there is only one copy of the static variable.

When the function is "static inline", there are as many copies as there are translation units.

The real question is now whether things are supposed to be this way, or if this is an ideosyncracy of the Microsoft C++ compiler.


Inlining means that executable code (instructions) is inlined into the calling function's code. The compiler can choose to do that regardless of whether you've asked it to. That has no effect on the variables (data) declared in the function.


Besides any design issues this all may imply, since you're already stuck with it, you should use static in this case not inline. That way everyone shares the same variables. (Static function)


I believe you will end up with one per translation unit. You've effectively got many versions of that function (and its declared static variable), one for every translation unit that includes the header.


Static means one copy is distributed throughout the program , but inline means it requires the same code for several time in the same program , so it is not possible to make a variable static inside the inline function.

참고URL : https://stackoverflow.com/questions/185624/static-variables-in-an-inlined-function

반응형