함수 / 메소드에 대해 키워드 '인라인'을 언제 작성해야합니까?
inline
C ++에서 함수 / 메소드 키워드는 언제 작성해야 합니까?
몇 가지 답변을 본 후 몇 가지 관련 질문이 있습니다.
언제해야 하지 ++ C에서 함수 / 메서드에 대한 키워드 '인라인'을 쓰기?
컴파일러는 언제 함수 / 메소드를 '인라인'으로 만들어야하는지 알 수 없습니까?
함수 / 메소드에 대해 '인라인'을 쓸 때 응용 프로그램이 멀티 스레딩 되는지 여부는 중요합니까 ?
오, 내 애완 동물 친구 중 하나
inline
컴파일러에게 함수를 인라인하도록 지시하는 지시문 과 비슷 static
하거나 그 extern
이상입니다. extern
, static
, inline
링커가 아닌 컴파일러에 의해 거의 독점적으로 사용하는 연결 지시어이다.
말했다되는 inline
컴파일러에 대한 힌트를 사용하면 함수가 인라인되어야한다 생각. 1998 년에는 그랬지만 10 년 후 컴파일러는 그러한 힌트를 필요로하지 않습니다. 코드 최적화와 관련하여 인간은 일반적으로 잘못된 것은 말할 것도 없으므로 대부분의 컴파일러는 '힌트'를 무시합니다.
static
-변수 / 함수 이름은 다른 번역 단위에서 사용할 수 없습니다. 링커는 실수로 다른 번역 단위에서 정적으로 정의 된 변수 / 함수를 사용하지 않도록해야합니다.extern
-이 변수 / 함수 이름을이 번역 단위에서 사용하지만 정의되지 않은 경우 불평하지 마십시오. 링커는 그것을 정렬하고 extern 기호를 사용하려고 시도한 모든 코드에 주소가 있는지 확인합니다.inline
-이 기능은 여러 번역 단위로 정의되므로 걱정하지 마십시오. 링커는 모든 변환 단위가 변수 / 함수의 단일 인스턴스를 사용하도록해야합니다.
참고 : 일반적으로 템플릿 inline
은 inline
이미 링크 의미가 있으므로 템플릿을 선언하는 것은 의미가 없습니다 . 그러나 명시 적 전문성 및 템플릿의 인스턴스화가 필요로inline
사용할 수 있습니다.
질문에 대한 구체적인 답변 :
-
C ++에서 함수 / 메소드에 대해 키워드 '인라인'을 언제 작성해야합니까?
함수를 헤더에 정의하려는 경우에만. 함수의 정의가 여러 변환 단위로 표시 될 수있는 경우에만 더 정확합니다. 헤더 파일에 작은 (하나의 라이너에서와 같이) 함수를 정의하면 코드를 최적화하는 동안 컴파일러에 더 많은 정보를 제공 할 수 있습니다. 또한 컴파일 시간이 증가합니다.
-
C ++에서 함수 / 메소드에 대해 키워드 '인라인'을 작성해서는 안되는 경우는 언제입니까?
컴파일러가 인라인하면 코드가 더 빨리 실행될 것이라고 생각하기 때문에 인라인을 추가하지 마십시오.
-
컴파일러는 언제 함수 / 메소드를 '인라인'으로 만들어야하는지 알 수 없습니까?
일반적으로 컴파일러는 사용자보다이 작업을 더 잘 수행 할 수 있습니다. 그러나 함수 정의가없는 컴파일러는 코드를 인라인하는 옵션이 없습니다. 최대한 최적화 된 코드에서는 일반적으로
private
요청 여부에 관계없이 모든 메소드가 인라인됩니다.GCC에서 인라인을 방지하기 위해을 사용
__attribute__(( noinline ))
하고 Visual Studio에서을 사용하십시오__declspec(noinline)
. -
함수 / 메소드에 대해 '인라인'을 쓸 때 응용 프로그램이 멀티 스레딩되는지 여부는 중요합니까?
멀티 스레딩은 어떠한 방식으로도 인라인에 영향을 미치지 않습니다.
남은 오해를 분산시키는 확실한 예를 통해이 스레드의 모든 위대한 답변에 기여하고 싶습니다.
다음과 같은 두 가지 소스 파일이 제공됩니다.
inline111.cpp :
#include <iostream> void bar(); inline int fun() { return 111; } int main() { std::cout << "inline111: fun() = " << fun() << ", &fun = " << (void*) &fun; bar(); }
inline222.cpp :
#include <iostream> inline int fun() { return 222; } void bar() { std::cout << "inline222: fun() = " << fun() << ", &fun = " << (void*) &fun; }
사례 A :
컴파일 :
g++ -std=c++11 inline111.cpp inline222.cpp
출력 :
inline111: fun() = 111, &fun = 0x4029a0 inline222: fun() = 111, &fun = 0x4029a0
토론 :
인라인 함수에 대해 동일한 정의를 가져야하더라도 C ++ 컴파일러는 그렇지 않은 경우 플래그를 지정하지 않습니다 (실제로 별도의 컴파일 로 인해 확인할 수있는 방법이 없음). 이것을 보장하는 것은 자신의 의무입니다!
링커에 대해 불평하지 않는 한 정의 규칙 으로,
fun()
로 선언됩니다inline
. 그러나 inline111.cpp 는fun()
컴파일러에서 처리 하는 첫 번째 변환 단위 (실제로 호출 )이므로 컴파일러 는 inline111.cppfun()
의 첫 번째 호출 발생을 인스턴스화 합니다. 컴파일러가 결정하면 되지 확장fun()
프로그램에서 다른 곳에서의 호출에 따라 ( 예 에서 inline222.cpp )에 대한 호출fun()
항상에서 생산의 인스턴스에 연결됩니다 inline111.cpp (호출fun()
내부 inline222.cpp해당 번역 단위에서 인스턴스를 생성 할 수도 있지만 연결되지 않은 상태로 유지됩니다. 실제로, 그것은 동일한&fun = 0x4029a0
인쇄물 에서 분명합니다 .마지막으로,에도 불구하고
inline
컴파일러에 제안 실제로 확장 한 - 라이너를fun()
, 그것을 무시 하기 때문에 분명하다 완전히 제안,fun() = 111
라인의 모두를.
사례 B :
컴파일 (역순 통지) :
g++ -std=c++11 inline222.cpp inline111.cpp
출력 :
inline111: fun() = 222, &fun = 0x402980 inline222: fun() = 222, &fun = 0x402980
토론 :
이 사례는 사례 A 에서 논의 된 내용을 주장한다 .
중요한 점
fun()
은 inline222.cpp 에서 실제 호출을 주석 처리하면 ( 예 :cout
inline222.cpp에서 주석을 완전히 주석 처리 ) 번역 단위의 컴파일 순서에도 불구하고fun()
첫 번째 호출 발생시 인스턴스화됩니다. inline111.cpp 이므로 케이스 B에 대한 인쇄 결과는 다음 과 같습니다inline111: fun() = 111, &fun = 0x402980
.
사례 C :
컴파일 (공지 -O2) :
g++ -std=c++11 -O2 inline222.cpp inline111.cpp
또는
g++ -std=c++11 -O2 inline111.cpp inline222.cpp
출력 :
inline111: fun() = 111, &fun = 0x402900 inline222: fun() = 222, &fun = 0x402900
토론 :
- 그대로 여기에 설명 ,
-O2
최적화하는 컴파일러 장려 실제로 확장 인라인 할 수있는 기능을 (공지 사항 또한-fno-inline
입니다 기본 최적화 옵션없이). 여기서 인쇄물에서 알 수 있듯이,fun()
실제로 는 특정 번역 단위 의 정의에 따라 인라인 확장 되어 두 가지 다른 인쇄물이 생성되었습니다 . 그럼에도 불구하고, 동일한 인쇄물 에서 알 수 있듯이 (표준에서 요구하는대로) 전 세계적으로 연결된 인스턴스 는 여전히 하나뿐입니다 .fun()
fun()
&fun
- 그대로 여기에 설명 ,
템플릿 특수화를 수행 할 때 (특수화가 .h 파일에있는 경우) 여전히 명시 적으로 함수를 인라인해야합니다.
1) 요즘은 거의 없습니다. 함수를 인라인하는 것이 좋은 생각이라면 컴파일러는 도움없이 함수를 수행합니다.
2) 항상. # 1을 참조하십시오.
(질문을 두 질문으로 나눈 것을 반영하도록 편집되었습니다 ...)
C ++에서 함수 / 메소드에 대해 키워드 '인라인'을 작성해서는 안되는 경우는 언제입니까?
함수가 .cpp
파일에 정의되어 있으면 키워드를 작성 하지 않아야 합니다.
컴파일러는 언제 함수 / 메소드를 '인라인'으로 만들어야하는지 알지 못합니까?
그러한 상황은 없습니다. 컴파일러는 함수를 인라인으로 만들 수 없습니다. 할 수있는 일은 함수에 대한 일부 또는 모든 호출을 인라인하는 것입니다. 함수의 코드를 얻지 못하면 그렇게 할 수 없습니다 (이 경우 링커는 그렇게 할 수 있으면 링커가해야합니다).
함수 / 메소드에 대해 '인라인'을 쓸 때 응용 프로그램이 멀티 스레딩되는지 여부는 중요합니까?
아니, 그건 전혀 중요하지 않습니다.
- 컴파일러는 언제 함수 / 메소드를 '인라인'으로 만들어야하는지 알지 못합니까?
이것은 사용 된 컴파일러에 따라 다릅니다. 오늘날 컴파일러는 인간보다 인라인하는 방법을 잘 알고 있으며 최적화를위한 힌트보다는 연결 지시문이기 때문에 성능상의 이유로 사용해서는 안된다는 것을 맹목적으로 신뢰하지 마십시오. 나는이 이론적으로이 논쟁들이 현실과 맞닥 뜨리는 것과는 다른 주장 일 수 있다는 데 동의한다.
여러 스레드를 읽은 후 방금 작업중 인 코드에 대한 인라인 효과에 대한 호기심을 시험해 보았습니다. 결과는 GCC의 속도가 빨라지고 인텔 컴파일러의 속도가 빨라지지 않았다는 것입니다.
(자세한 내용 : 클래스 외부에 정의 된 중요 기능이 거의없는 수학 시뮬레이션, GCC 4.6.3 (g ++ -O3), ICC 13.1.0 (icpc -O3). 중요 포인트에 인라인을 추가하면 GCC 코드의 속도가 6 % 증가했습니다.
따라서 GCC 4.6을 최신 컴파일러로 사용할 경우 CPU 집약적 작업을 작성하고 병목 현상이 어디에 있는지 정확히 알고 있으면 인라인 지시문이 여전히 중요합니다.
실제로는 거의 없습니다. 당신이하고있는 일은 컴파일러가 주어진 함수를 인라인으로 만드는 것을 제안하는 것입니다 (예 :이 함수 / w 본문에 대한 모든 호출을 대체하십시오). 물론 보장은 없습니다 : 컴파일러는 지시어를 무시할 수 있습니다.
컴파일러는 일반적으로 이와 같은 것을 감지하고 최적화하는 데 효과적입니다.
gcc는 최적화를 사용하지 않고 컴파일 할 때 기본적으로 함수를 인라인하지 않습니다. 나는 Visual Studio에 대해 모른다 – deft_code
/ FAcs로 컴파일하고 어셈블리 코드를 보면 Visual Studio 9 (15.00.30729.01)에서이를 확인했습니다. 컴파일러는 디버그 모드 에서 최적화를 사용하지 않고 멤버 함수에 대한 호출을 생성했습니다 . 함수가 __forceinline 으로 표시 되더라도 인라인 런타임 코드는 생성되지 않습니다.
리턴 유형 전에 맨 처음에 배치하려고합니다. 그러나 대부분의 컴파일러는이를 무시합니다. 정의되고 더 작은 코드 블록이있는 경우 대부분의 컴파일러는 어쨌든 인라인으로 간주합니다.
코드를 개발하고 디버깅 할 때는 inline
제외하십시오. 디버깅이 복잡합니다.
추가 한 주요 이유는 생성 된 코드를 최적화하는 데 도움이되기 때문입니다. 일반적으로 이것은 증가 된 코드 공간을 속도로 교환하지만 때로는 inline
코드 공간과 실행 시간을 절약합니다.
알고리즘 완성 전의 성능 최적화에 대한 이런 종류의 생각은 조기 최적화 입니다.
인라인해야 할 때 :
1. 매개 변수 전달, 제어 전달, 제어 반환 등과 같이 함수가 호출 될 때 발생하는 오버 헤드를 피하고 싶을 때
2. 기능은 작고, 자주 호출되며 인라인을 만드는 것은 80-20 규칙에 따라 프로그램 성능에 큰 영향을 미치는 인라인으로 만들려고 시도하기 때문에 실제로 유리합니다.
우리가 알고 있듯이 인라인은 레지스터와 비슷한 컴파일러에 대한 요청 일 뿐이며 객체 코드 크기로 비용이 발생합니다.
라이브러리를 작성하거나 특별한 이유가 없으면 링크 타임 최적화 를 잊어 버리고 대신 inline
사용할 수 있습니다 . 컴파일 단위 전체에서 인라인하기 위해 함수 정의가 헤더에 있어야한다는 요구 사항을 제거합니다 .inline
(그러나 링크 시간 최적화를 사용하지 않는 이유가 있습니까? )
C ++ 인라인 함수는 클래스에서 일반적으로 사용되는 강력한 개념입니다. 함수가 인라인 인 경우 컴파일러는 컴파일시 함수가 호출되는 각 지점에 해당 함수의 코드 사본을 배치합니다.
인라인 함수를 변경하면 컴파일러가 모든 코드를 다시 한 번 바꿔야하므로 함수의 모든 클라이언트를 다시 컴파일해야 할 수 있습니다. 그렇지 않으면 이전 기능이 계속됩니다.
함수를 인라인하려면 함수 이름 앞에 키워드를 인라인으로 놓고 함수를 호출하기 전에 함수를 정의하십시오. 정의 된 함수가 한 줄 이상인 경우 컴파일러는 인라인 한정자를 무시할 수 있습니다.
클래스 정의의 함수 정의는 인라인 지정자를 사용하지 않아도 인라인 함수 정의입니다.
다음은 인라인 함수를 사용하여 최대 두 숫자를 반환하는 예입니다.
#include <iostream>
using namespace std;
inline int Max(int x, int y) { return (x > y)? x : y; }
// Main function for the program
int main() {
cout << "Max (100,1010): " << Max(100,1010) << endl;
return 0;
}
'Programming' 카테고리의 다른 글
Git의 사인 오프 기능은 무엇입니까? (0) | 2020.02.11 |
---|---|
require ()와 library ()의 차이점은 무엇입니까? (0) | 2020.02.11 |
인터페이스를 구현하는 모든 유형 얻기 (0) | 2020.02.11 |
jQuery를 사용하여 동적 HTML 요소에 이벤트를 어떻게 첨부합니까? (0) | 2020.02.11 |
들여 쓰기 오류 : 들여 쓰기가 외부 들여 쓰기 레벨과 일치하지 않습니다 (0) | 2020.02.11 |