c++: is there a way to ensure the compiler that calling twice the same const method gives the same result?

141 Views Asked by At

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?

1

There are 1 best solutions below

3
On BEST ANSWER

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.