최소 실행 가능 예
이 멋진 C ++ 17 기능을 통해 다음을 수행 할 수 있습니다.
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return ¬main_i;
}
컴파일 및 실행 :
g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main
GitHub 업스트림 .
참고 항목 : 인라인 변수는 어떻게 작동합니까?
인라인 변수에 대한 C ++ 표준
C ++ 표준은 주소가 동일하다는 것을 보장합니다. C ++ 17 N4659 표준 초안
10.1.6 "인라인 지정자":
6 외부 연결이있는 인라인 함수 또는 변수는 모든 변환 단위에서 동일한 주소를 가져야합니다.
cppreference https://en.cppreference.com/w/cpp/language/inline는 경우라고 설명 static
지정되어 있지 않은 경우, 그것은 외부 링크가 있습니다.
GCC 인라인 변수 구현
우리는 그것이 어떻게 구현되는지 관찰 할 수 있습니다 :
nm main.o notmain.o
포함하는:
main.o:
U _GLOBAL_OFFSET_TABLE_
U _Z12notmain_funcv
0000000000000028 r _ZZ4mainE19__PRETTY_FUNCTION__
U __assert_fail
0000000000000000 T main
0000000000000000 u notmain_i
notmain.o:
0000000000000000 T _Z12notmain_funcv
0000000000000000 u notmain_i
그리고 man nm
에 대해 말한다 u
:
"u"기호는 고유 한 글로벌 기호입니다. 이것은 ELF 심볼 바인딩의 표준 세트에 대한 GNU 확장입니다. 이러한 심볼의 경우 동적 링커는 전체 프로세스에서이 이름과 유형이 사용중인 심볼이 하나만 있는지 확인합니다.
이를위한 전용 ELF 확장이 있음을 알 수 있습니다.
C ++ 이전 17 : extern const
C ++ 17 이전과 C에서는를 사용하여 매우 유사한 효과를 얻을 수 있으며 extern const
,이 경우 단일 메모리 위치가 사용됩니다.
단점 inline
은 다음과 같습니다.
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
notmain.cpp
#include "notmain.hpp"
const int notmain_i = 42;
const int* notmain_func() {
return ¬main_i;
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
extern const int notmain_i;
const int* notmain_func();
#endif
GitHub 업스트림 .
Pre-C ++ 17 헤더 전용 대안
이들은 extern
솔루션 만큼 좋지는 않지만 작동하며 단일 메모리 위치 만 차지합니다.
constexpr
때문에 기능, constexpr
의미inline
와 inline
수 (힘) 정의는 모든 번역 단위에 표시합니다 :
constexpr int shared_inline_constexpr() { return 42; }
괜찮은 컴파일러가 호출을 인라인 할 것이라고 장담합니다.
다음 과 같이 const
또는 constexpr
정적 정수 변수를 사용할 수도 있습니다 .
#include <iostream>
struct MyClass {
static constexpr int i = 42;
};
int main() {
std::cout << MyClass::i << std::endl;
// undefined reference to `MyClass::i'
//std::cout << &MyClass::i << std::endl;
}
그러나 주소를 가져 오는 것과 같은 작업을 수행 할 수 없습니다. 그렇지 않으면 odr이 사용됩니다. https://en.cppreference.com/w/cpp/language/static "Constant static members"및 constexpr 정적 데이터 정의 도 참조하십시오. 회원
씨
C에서 상황은 C ++ 이전 C ++ 17과 동일합니다. 다음 위치에 예제를 업로드했습니다. C에서 "정적"은 무엇을 의미합니까?
유일한 차이점은 C ++에서는 전역을 const
의미 static
하지만 C에서는 그렇지 않다는 것입니다 .`static const` 대`const`의 C ++ 의미 체계
완전히 인라인 할 방법이 있습니까?
TODO : 메모리를 전혀 사용하지 않고 변수를 완전히 인라인 할 수있는 방법이 있습니까?
전처리 기가하는 것과 매우 비슷합니다.
이것은 어떻게 든 필요합니다.
- 변수의 주소가 사용되는지 여부를 금지하거나 감지
- 해당 정보를 ELF 개체 파일에 추가하고 LTO가이를 최적화하도록합니다.
관련 :
Ubuntu 18.10, GCC 8.2.0에서 테스트되었습니다.
const
.