【问题标题】:c++: is there a way to ensure the compiler that calling twice the same const method gives the same result?c++:有没有办法确保编译器调用两次相同的 const 方法得到相同的结果?
【发布时间】: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


【解决方案1】:

成员函数是const-qualified 并不意味着该函数没有任何副作用。在没有看到函数定义的情况下,编译器无法确定该函数不会将某些内容输出到文件中,也不会通过网络发送某些内容等。因此,通常,仅调用一次相同的成员函数可能不会产生等效的结果调用它两次(尽管函数是const-qualified)。

编辑:回答原始问题:目前,没有标准方法可以将函数标记为没有副作用。一些编译器可能支持自定义属性,例如[[gnu::pure]][[gnu::const]],但这不是标准的。

【讨论】:

  • 这是准确的,但没有回答问题,即如何与编译器沟通该函数没有副作用。
  • C++ [[pure]]N3744 (2013)P0078R0 (2015) 中提出,但尚未成为标准(还没有?)。
  • 一个const 成员函数仅仅意味着const T *this。它仍然可以改变一个全局变量(例如,即使它伪装成只读的缓存),或者它的 args 指向的内存; I/O 并不是唯一可能的副作用。 (或者甚至在一些指针上抛弃const...)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-20
  • 2021-03-04
  • 1970-01-01
  • 2018-01-22
  • 2015-01-23
相关资源
最近更新 更多