Coo*_*ter 24 c++ function-pointers constexpr
在程序执行之前,编译器如何知道平方根在内存中的位置?我认为每次执行程序时地址都会不同,但这样做有效:
constexpr double(*fp)(double) = &sqrt;
cout << fp(5.0);
Run Code Online (Sandbox Code Playgroud)
是因为地址是相对于内存中的另一个地址吗?我不这么认为,因为它的值fp很大:0x720E1B94.
Nic*_*las 25
在编译时,编译器不知道地址sqrt.但是,您无法在编译时使用constexpr函数指针执行任何操作,该指针允许您访问该指针的地址.因此,编译时的函数指针可以视为不透明值.
并且由于在初始化之后无法更改constexpr变量,因此每个constexpr函数指针都可以归结为特定函数的位置.
如果你做了这样的事情:
using fptr = float(*)(float);
constexpr fptr get_func(int x)
{
return x == 3 ? &sqrtf : &sinf;
}
constexpr fptr ptr = get_func(12);
Run Code Online (Sandbox Code Playgroud)
编译器可以准确地检测哪个函数get_func将返回任何特定的编译时间值.所以get_func(12)减少到&sinf.所以&sinf编译到的任何东西都是get_func(12)编译到的.
SHH*_*SHH 17
地址值由链接器分配,因此编译器不知道确切的地址值.
cout << fp(5.0);
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为它在解析完确的地址后在运行时进行评估.
通常,您不能使用constexpr指针的实际值(地址),因为它在编译时是未知的.
Bjarne Stroustrup的C++编程语言第4版提到:
10.4.5地址常量表达式
静态分配的对象(第6.4.2节)的地址(例如全局变量)是常量.但是,它的值由链接器而不是编译器分配,因此编译器无法知道此类地址常量的值.这限制了指针和引用类型的常量表达式的范围.例如:
Run Code Online (Sandbox Code Playgroud)constexpr const char? p1 = "asdf"; constexpr const char? p2 = p1; // OK constexpr const char? p2 = p1+2; // error : the compiler does not know the value of p1 constexpr char c = p1[2]; // OK, c==’d’; the compiler knows the value pointed to by p1
这很简单。
考虑编译器如何知道在这段代码中调用的地址:
puts("hey!");
Run Code Online (Sandbox Code Playgroud)
Compiler 不知道 的位置puts,也没有为其添加运行时查找(这对性能来说相当糟糕,尽管它实际上是类的虚拟方法需要做的)。在运行时拥有不同版本的动态库的可能性(更不用说地址空间布局随机化,即使它是完全相同的库文件)确保构建时工具链链接器也不知道它。
所以当它启动编译的二进制程序时,由动态链接器来修复地址。这称为重定位。
完全相同的事情发生在你的constexpr:编译器使用这个地址将代码中的每个地方添加到重定位表中,然后动态链接器在每次程序启动时完成它的工作。
| 归档时间: |
|
| 查看次数: |
2540 次 |
| 最近记录: |