C ++의 인라인 함수 점은 무엇인가?


19

내가 읽은 것에 따르면, 컴파일러는 인라인 함수의 함수 호출을 본문으로 대체 할 의무는 없지만 가능하다면 그렇게 할 것입니다. 이것은 나에게 생각을 줬다 – 만약 그렇다면 우리는 왜 인라인 단어를 가지고 있는가? 기본적으로 모든 함수를 인라인 함수로 만들고 컴파일러가 함수를 호출로 대체 할 수 있는지 알아 내지 않겠습니까?


1
이곳까지 . 페이지 6
EpsilonVector

답변:


40

inlineC 출신이고; C ++에는 처음이 아니 었습니다.

프로그래머가 코드 최적화를 지원할 수 있도록 설계된 C 키워드 ( registerinline)가 있습니다. 컴파일러는 레지스터 할당에서 더 나은 기능을 수행하고 함수를 인라인 할시기를 결정할 수 있기 때문에 일반적으로 오늘날 무시됩니다 (사실 컴파일러는 다른 시간에 함수를 인라인하거나 인라인하지 않을 수 있음). 최신 프로세서의 코드 생성은 Ritchie가 C를 발명 할 때 일반적으로 사용되는 결정 론적 코드보다 훨씬 복잡합니다.

현재 C ++에서이 단어의 의미는 여러 개의 동일한 정의를 가질 수 있으며이를 사용하는 모든 번역 단위에서 정의되어야한다는 것입니다. (즉, 인라인 될 수 있는지 확인해야합니다.) inline문제없이 헤더에 함수를 가질 수 있으며 클래스 정의에 정의 된 멤버 함수는 자동으로 효과적 inline입니다.


3
의 역사는 +1입니다 inline.
Tamara Wijsman

11
나는 inline그것이 C에서 공급 업체 확장으로 이미 사용 가능했지만 C ++로 먼저 표준화 되었다는 것을 확신합니다 ... 예, C99의 C 표준에 추가 된 것으로 보입니다.
Ben Voigt

@ Ben Voigt : 네 말이 맞아. 나는 C에서 처음 만났다.
David Thornley

5
또한 이력이 잘못되었을뿐 아니라 inlineC99 이상의 규칙 inline은 C ++ 의 규칙과 다릅니다 .
Alf P. Steinbach

27

원래 inline는 함수 호출이 인라인되어야한다는 매우 강력한 힌트였습니다.

그러나 유일하게 보장되는 효과 inline는 함수를 여러 번역 단위로 정의 할 수 있도록하는 것입니다. 예를 들어, 정의를 헤더 파일에 배치하는 것입니다.

오늘날 일부 컴파일러는 g ++과 같은 인라인 힌트를 따르는 데 매우 관심이 있습니다. 그리고 일부 컴파일러는 Visual C ++와 같이 덜 심각합니다. 그러나 모두 보증을 준수해야합니다.

불행히도 최적화 힌트와 링커 레벨 폐기 가능 정의라고하는이 두 가지 의미는 동일한 키워드로 존재한다는 것은 불행히도 실제로는 다른 의미없이 하나를 가질 수 없기 때문입니다.

불행히도 inline(또는 더 나은 경우, 폐기 가능한 정의에 대한 별도의 키워드) ¹ 데이터에 적용 할 수 없습니다 .

헤더 전용 모듈이 널리 보급됨에 따라 링커 레벨 폐기 가능 데이터의 필요성이 증가했습니다. 예를 들어, 많은 Boost 하위 라이브러리는 헤더 전용입니다.

그러나 데이터의 경우 템플릿을 사용하여 약간의 트릭을 적용 할 수 있습니다. 일부 클래스 템플릿에서 정의하고 typedef템플릿 매개 변수 void(또는 무엇이든)를 제공하십시오. 하나의 정의 규칙이 템플릿에 대해 특정 예외를 만들기 때문입니다.

참고 :
¹ inline변수는 C ++ 17에서 지원됩니다 .


1
에 대한 추가 정보는 +1입니다 inline.
Tamara Wijsman

1
" 실제로 동일하게 "는 잘못 설계 한 C ++ 언어가 일반적으로 유능하고 신중한 프로그래머가 정적 개체를 사용하는 합리적이지만 공식적으로 정의되지 않은 코드를 작성하려고하기 때문에 매우 까다로운 조건입니다.
curiousguy

6

기본적으로 모든 기능을 인라인으로 설정하지 않는 이유는 무엇입니까? 엔지니어링 트레이드 오프이기 때문입니다. "최적화"에는 최소한 두 가지 유형이 있습니다. 프로그램 속도를 높이고 프로그램의 크기 (메모리 공간)를 줄입니다. 인라인은 일반적으로 속도를 높입니다. 스택에서 매개 변수를 밀고 당기는 것을 피하면서 함수 호출 오버 헤드를 제거합니다. 그러나 모든 함수 호출은 이제 함수의 전체 코드로 대체되어야하기 때문에 프로그램의 메모리 풋 프린트가 더 커집니다. 보다 복잡한 작업을 수행하기 위해 CPU는 자주 사용되는 메모리 청크를 CPU의 캐시에 저장하여 매우 빠르게 액세스 할 수 있습니다. 프로그램의 메모리 이미지를 충분히 크게 만들면 프로그램에서 캐시를 효율적으로 사용할 수 없으며 최악의 경우 인라인으로 인해 실제로 프로그램 속도가 느려질 수 있습니다.


5
그러나 컴파일러는 일반적으로 프로그래머보다 훨씬 더 잘 이해할 수 있습니다. 따라서 이것은 유효한 주장이 아닙니다.
Konrad Rudolph

" 모든 함수 호출은 이제 함수의 전체 코드로 대체되어야합니다. "인라인 함수는 호출 시퀀스가 ​​생략되고 함수의 어셈블리 코드가 복사되는 함수가 아닙니다. 높은 수준의 중간 코드를 인라인으로 가져 와서 인라인 함수가 컴파일됩니다. 이를 통해 컴파일러는 함수 본문을 클린 매크로 (클린 매크로는 C 전 처리기 매크로의 단점이없는 매크로)로 효과적으로 처리 할 수 ​​있으며 잠재적으로 많은 최적화가 가능합니다.
curiousguy

3

“인라인”을 이해하려면 역사와 20 년 전과 30 년 전의 삶이해해야합니다.

메모리가 거의없는 컴퓨터에서 코드를 작성하고 있었기 때문에 컴파일러가 프로그램을 구성하는 모든 코드를 한 번에 처리 할 수 ​​없었습니다. 컴파일러도 매우 느리기 때문에 변경되지 않은 코드를 다시 컴파일 할 필요가 없었습니다. 24 시간 이상 (최고급 자동차보다 비싼 컴퓨터에서) 모든 코드를 다시 컴파일하는 데 몇 가지 프로젝트가 정상이었습니다. 에서 일하는.

따라서 각 코드 파일은 개별적으로 오브젝트 파일로 컴파일되었습니다. 각 객체 파일은 함수의 "주소"와 함께 포함 된 모든 함수 목록으로 시작되었습니다. 또한 객체 파일에는 호출 위치와 함께 다른 객체 파일에서 호출 한 모든 함수 목록이 있습니다.

링커는 먼저에게 오브젝트 파일을 읽고, 그들은 그들이에 있던 파일이 주소와 함께 수출 모든 기능의 목록을 구축 할 것입니다. 그런 다음 모든 "외부"함수 호출을 함수 주소로 업데이트하면서 모든 객체 파일을 다시 읽고 프로그램 파일로 출력합니다.

링커는 외부 함수 호출에 대한 참조를 수정하는 것 이외의 다른 방법으로 컴파일러가 생성 한 기계어 코드를 변경하거나 최적화하지 않았습니다. 링커는 운영 체제의 일부였으며 대부분의 컴파일러보다 오래되었습니다. 사람들이 새 컴파일러를 작성할 때 현재 링커와 함께 작동하고 현재 객체 파일에 링크 할 수 있어야했습니다. 그렇지 않으면 시스템 호출을 할 수 없었습니다.

컴파일러는 포함 된 모든 헤더 파일과 함께 컴파일되는“.c”또는“.cpp”파일의 코드 만 보았습니다. 따라서 다른“.c”또는“.cpp”파일의 코드를 기반으로 최적화를 수행 할 수 없었습니다.

“inline”키워드를 사용하면 함수 본문 (메서드)을 헤더 파일에 정의 할 수 있으므로 컴파일러는이를 호출하는 코드를 컴파일하는 동안 함수 코드를 사용할 수 있습니다. 예를 들어 다른 .cpp 파일에 컬렉션 클래스가 정의되어 있다고 가정하면이 클래스에는 한 줄의 코드가 포함 된 "isEmpty"메서드가 있으며 함수를 호출하는 대신 결과 프로그램의 속도가 크게 향상됩니다 함수 호출이이 한 줄로 대체되었습니다.

"inline"키워드는 당시 많은 프로그래머가 객체의 개인 필드에 액세스하지 않고도 함수 호출 비용을 피하면서 데이터를 캡슐화 할 수있는 "싸고 쉬운"방법으로 여겨졌습니다. (당시에 일반적인 코드를 "인라이닝"하는 훨씬 나쁜 방법입니다.)

요즘“링커”는 많은 코드 최적화를 수행하며 일부 팀에서 컴파일러로 작성하는 경향이 있습니다. 컴파일러는 종종 코드가 올바른지 확인하고이를“압축”하여 대부분의 기계 코드 작성 작업을 링커에 남겨 둡니다.


2

표준의 내용 (굵게 강조 표시된 중요 부분)을 살펴 보겠습니다.

2. 인라인 지정자가있는 함수 선언은 인라인 함수를 선언합니다. 인라인 지정자는 호출 시점에서 함수 본문의 인라인 대체 가 일반적인 함수 호출 메커니즘 보다 선호 됨을 구현에 표시합니다 . 호출 시점 에서이 인라인 대체 를 수행하기 위해 구현이 필요하지 않습니다 . 그러나이 인라인 대체가 생략 되더라도 인라인 함수에 대한 다른 규칙은 여전히 ​​준수해야합니다.

C ++ 표준, ISO / IEC 14882 : 2003 , 7.1.2 함수 지정자 [dcl.fct.spec]

따라서 확실하게하려면 컴파일러 설명서를 읽어야합니다.

많은 머신 코드가 복제 될 수 있으므로 모든 것을 인라인하는 것은 나쁜 생각입니다 ...

따라서 다음을 알아야합니다.

간단한 대답은 없습니다 . 가장 좋은 것을 보려면 그것을 가지고 놀아야합니다. 마 하지 "결코 사용과 같은 단순한 답을 정착 inline기능"또는 "항상 사용 inline기능"또는 "사용 inline기능이 적은 코드의 N 라인보다의 경우에만 작동합니다." 이러한 모든 규모에 맞는 규칙을 작성하기는 쉽지만 최적의 결과를 낼 수는 없습니다.

C ++ FAQ, 인라인 함수 , 9.3 inline함수가 성능을 향상 시킵니까?


1
당신이 말하는 것은 사실이지만, 프로그래머로서 인라인인지 아닌지에 대한 결정이 아니기 때문에 관련성이 없습니다. 키워드를 넣으면 함수가 인라인되거나되지 않을 수 있습니다. 키워드를 넣지 않아도 여전히 인라인 될 수 있습니다. 키워드를 넣을 때 컴파일러가 실제로 결정을 내리는 것에 대해 어떤 규칙을 갖는 것은 의미가 없습니다.
Kate Gregory

그것이 당신과 정확히 같다면 어떻게 관련이 없습니까? 간단한 답변이 없습니다 .
Tamara Wijsman

OP 질문에 답하지 않기 때문에 관련이 없습니다. 그는 "인라인이하는 일"을 묻지 않고 "무엇을 요점"을 묻습니다. 그리고 당신의 대답은 우리가 이미 인라인에 대해 알고있는 것을 되풀이합니다.
Davor Ždralo

@Davor : "무엇이 요점입니까?" FAQ를 준수하지 않으므로 질문에 제기 된 질문에 답변하고 있습니다. 나는 inlineOP가 부분을 놓친 것처럼 지식을 되풀이 하여 요점을 말하고 있습니다. 이것이 그가 요점을 얻지 못하는 핵심 이유입니다. 포인트를 얻으려면 그 포인트 아래에 무엇이 있는지 이해해야합니다.
Tamara Wijsman

대체 왜 FAQ를 준수하지 않습니까? 표준은 인라인 키워드의 구문과 의미를 설명하며 OP 질문은 목적, 사용시기, 해결해야 할 문제는 무엇입니까? 이것이 FAQ를 어떻게 준수하지 않는지 알 수 없습니다.
Davor Ždralo

1

인라인 키워드를 사용하는 좋은 이유를 알려 드리겠습니다.

티켓 프린터 또는 이와 유사한 소형 시스템과 같은 내장 시스템 프로세서는 매우 제한되어 있으며 함수 호출 (스택에서 함수 매개 변수 준비, 호출, 스택에서 매개 변수 가져 오기 및 답장 등)은 함수 자체 옆에서 실행하는 데 몇 ms가 걸릴 수 있습니다.

호출 시간은 약 60ms (실제 기능이 아닌 호출 전용)이고 50 회 반복합니다 (루프 또는 반복 호출 트리).

해당 함수 호출에서 앞뒤로 이동하는 데 60 * 50 = 3000 (3 초)이 걸립니다.

메모리가 있다면 확실히 3 초를 절약하기 위해 인라인을 수행 할 것입니다.

따라서 인라인은 기본적으로 실행 속도가 필요할 때 사용됩니다. 내가 참여한 일부 프로젝트에서 호출 시간은 실행 시간보다 길었습니다. 인라인을 사용할 때의 전형적인 상황입니다.


어? 코드에 인라인을 넣었다고해서 컴파일러가 실제로 인라인한다는 것을 의미하지는 않으며, 거기에 넣지 않는다는 의미도 아닙니다. 그것은 단지 힌트 일 뿐이며 오늘날의 컴파일러는 대부분 무시합니다. 컴파일러가 인라인하는 것이 유용하다고 생각하면 그렇지 않을 것입니다. 거기에는 실제적인 통제력이 없습니다. OP는 이미 이것을 알고 있으며 다음과 같이 묻습니다. "무엇입니까?". 도대체 누가 +1을합니까? 키워드 인라인이 인라인을 강요하고 있음을 암시하고 질문과 관련이 없습니다.
Davor Ždralo

2
@Davor Ždralo 무례 할 필요는 없습니다. 인라인을 사용해야하는 이유는 무엇입니까? 내 요점은 메모리 비용으로 코드를 더 빨리 얻을 수 있다는 것을 보여주었습니다. 각 컴파일러는 인라인 키워드를 다르게 처리 할 수 ​​있으므로 언급하지 않은 문서를 확인해야합니다. 인라인으로 생성되는 추가 메모리 오버 헤드를 항상 감당할 수는 없으므로 사용할 때 "안내"하는 것이 유용합니다. 또한 인라인이 적용되었다고 말하지 않았습니다. 누군가이 답변이 도움이되었고 +1로 투표했습니다. 다른 사람이 다른 수준의 경험을 가지고 있고 사소한 유용한 것을 찾을 수 있음을 존중하십시오.
Max Kielland
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.