【发布时间】:2021-02-16 09:34:43
【问题描述】:
我对以下2个简单的sn-ps感到困惑:
#include <vector>
struct A{
int foo(int i) const {return v[i];}
std::vector<int> v;
};
int f(const A &a, int i) {
int j;
j=a.foo(i);
j=a.foo(i);
return j;
}
给出汇编代码:
movsxd rax, esi
mov rcx, qword ptr [rdi]
mov eax, dword ptr [rcx + 4*rax]
ret
和
#include <vector>
struct A{
int foo(int i) const;
std::vector<int> v;
};
int f(const A &a, int i) {
int j;
j=a.foo(i);
j=a.foo(i);
return j;
}
给出:
push rbp
push rbx
push rax
mov ebp, esi
mov rbx, rdi
call _ZNK1A3fooEi
mov rdi, rbx
mov esi, ebp
add rsp, 8
pop rbx
pop rbp
jmp _ZNK1A3fooEi # TAILCALL
在第一种情况下,编译器“看到”函数foo 的内部,并知道他不必调用它两次。在第二种情况下,它只有它的声明,它似乎不能假设它可以只调用一次函数,而函数是 const... 为什么会这样?这是i 和函数内部foo 之间的别名问题吗?如果这是一个别名问题,我如何确保编译器不担心这个问题?
【问题讨论】:
-
除非我遗漏了什么,否则两个代码块都是一样的
-
函数是
const并不意味着每次调用它都不能返回不同的值。仅表示该功能不会改变*this。 -
一些编译器有办法指定,但这不是标准的。参见例如gcc __attribute__(const)
-
@janou195 例如,编译器没有看到的函数可能是
int A::foo(int i) const { return rand(); }。 -
第二个
A.foo()的实现在哪里?双重j=a.foo(i);的目的是什么?
标签: c++ assembly optimization inline pure-function