I am puzzled with the following 2 simple snippets:
#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;
}
which gives the assembly code:
movsxd rax, esi
mov rcx, qword ptr [rdi]
mov eax, dword ptr [rcx + 4*rax]
ret
and
#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;
}
which gives:
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
In the first case, the compilers 'sees' the internal of the function foo
and get that he does not have to call it twice. In the second case, it just has its declaration, and it seems that it cannot assume that it can call the function just once, whereas the function is const... Why is that? Is this an aliasing problem between i
and the internal of the function foo
? If this is an aliasing problem, how can I ensure the compiler not to worry about that?
The fact that the member function is const
-qualified does not mean that the function does not have any side effects. Without seeing function definition, the compiler cannot be sure that the function doesn't output something into a file, doesn't send something over the network, etc. Thus, in general, calling the same member function only once may not produce results equivalent to calling it twice (despite the function being const
-qualified).
Edit: To answer the original question: currently, there is no standard way to mark a function as having no side effects. Some compilers may support custom attributes, such as [[gnu::pure]]
and [[gnu::const]]
, but this is not standard.