edg*_*eis 53
通常的模式是:
extern const int a_global_var;#include "file.h" const int a_global_var = /* some const expression */;编辑:合并legends2k的评论.谢谢.
C ++ 17 inline变量
如果您认为自己想要一个extern const,那么您实际上更可能希望使用C ++ 17内联变量。
强大的C ++ 17功能使我们能够:
constexpr:如何声明constexpr extern?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);
}
Run Code Online (Sandbox Code Playgroud)
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
Run Code Online (Sandbox Code Playgroud)
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return ¬main_i;
}
Run Code Online (Sandbox Code Playgroud)
编译并运行:
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
Run Code Online (Sandbox Code Playgroud)
另请参阅:内联变量如何工作?
内联变量的C ++标准
C ++标准保证地址相同。C ++ 17 N4659标准草案 10.1.6“内联说明符”:
6具有外部链接的内联函数或变量在所有翻译单元中应具有相同的地址。
cppreference https://zh.cppreference.com/w/cpp/language/inline解释说,如果static未给出,则具有外部链接。
内联变量实现
我们可以观察到它是如何实现的:
nm main.o notmain.o
Run Code Online (Sandbox Code Playgroud)
其中包含:
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
Run Code Online (Sandbox Code Playgroud)
并man nm说u:
“ u”符号是唯一的全局符号。这是对ELF符号绑定的标准集合的GNU扩展。对于这样的符号,动态链接器将确保在整个过程中只有一个使用此名称和类型的符号。
因此,我们看到有专用的ELF扩展程序。
C ++ 17之前的版本: extern const
extern const确实可以按照下面的示例工作,但缺点inline是:
constexpr使用这种技术不可能创建变量,只能inline允许:如何声明constexpr extern?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);
}
Run Code Online (Sandbox Code Playgroud)
notmain.cpp
#include "notmain.hpp"
const int notmain_i = 42;
const int* notmain_func() {
return ¬main_i;
}
Run Code Online (Sandbox Code Playgroud)
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
extern const int notmain_i;
const int* notmain_func();
#endif
Run Code Online (Sandbox Code Playgroud)
C ++ 17之前的标头仅替代品
这些不如extern解决方案那样好,但是它们可以工作并且仅占用一个内存位置:
一个constexpr函数,因为constexpr隐含inline并inline 允许(强制)定义出现在每个翻译单元上:
constexpr int shared_inline_constexpr() { return 42; }
Run Code Online (Sandbox Code Playgroud)
我敢打赌,任何不错的编译器都会内联该调用。
您还可以使用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;
}
Run Code Online (Sandbox Code Playgroud)
但是您不能做诸如获取其地址之类的事情,否则它会变得奇怪,请参见:https : //en.cppreference.com/w/cpp/language/static “恒定静态成员”和定义constexpr静态数据成员
有什么办法可以完全内联吗?
TODO:有什么方法可以完全内联变量,而无需使用任何内存?
就像预处理器一样。
这将需要某种方式:
有关:
在Ubuntu 18.10,GCC 8.2.0中进行了测试。
你可以一起使用它们.但是你需要在使用const时保持一致,因为当C++命名装饰时,const包含在用于装饰符号名称的类型信息中.所以extern const int i会引用一个不同的变量extern int i
除非你使用extern"C"{}.C名称装饰不注意const.
| 归档时间: |
|
| 查看次数: |
48338 次 |
| 最近记录: |