“ this->”对成员变量的访问性能

时间:2019-03-22 11:50:50

标签: c++

我刚刚与我的cpp导师进行了激烈的讨论,讨论如何使用this->与“只是名字”来进行成员变量访问。

class Test{
  int a;
  int data[50000000];
  int b;

  Test(int c,int d){
    a=c; //or this->a=c;
    b=d; //or this->b=d;
  }
};

他的理解是,纯名称表示对成员变量的引用,而使用this->会扩展为(*this).,我同意后者。 出于性能原因,您将使用对变量的引用,因为延迟访问指针会将整个对象复制到适当位置,然后才访问一部分。由于这种情况曾经发生在this->上,因此会对性能产生很大的影响。

但是我已经尝试过将两个版本都翻译成程序集,并且没有区别。这是为什么? (我不习惯集会来理解整个上下文,所以我不知道)

在这种情况下,编译器是否不使用引用,而是使用更类似于取消引用的内容,还是只是不进行我期望它执行的操作? (如果有的话,我们一直在谈论c ++ 11)

1 个答案:

答案 0 :(得分:0)

在带和不带this->的情况下访问非静态成员函数中的成员将导致相同的机器代码。后者是前者的语法糖。代码

class A {
public:
    int a;
    A() {
        a = 1;
    }
};

class B {
public:
    int b;
    B() {
        this->b = 1;
    }
};

int main() {
    A a;
    B b;
    return 0;
}

无需优化即可翻译为

main:                                   # @main
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     dword ptr [rbp - 4], 0
        lea     rdi, [rbp - 8]
        call    A::A() [base object constructor]
        lea     rdi, [rbp - 16]
        call    B::B() [base object constructor]
        xor     eax, eax
        add     rsp, 16
        pop     rbp
        ret
A::A() [base object constructor]:                              # @A::A() [base object constructor]
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 8], rdi
        mov     rax, qword ptr [rbp - 8]
        mov     dword ptr [rax], 1
        pop     rbp
        ret
B::B() [base object constructor]:                              # @B::B() [base object constructor]
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 8], rdi
        mov     rax, qword ptr [rbp - 8]
        mov     dword ptr [rax], 1
        pop     rbp
        ret

取消引用指针不会复制对象,但会产生对该对象的引用。否则类似

int a(0);
int pa = &a;
*pa = 12;
std::cout << a << '\n'; // prints 12

将无法按预期工作。同样,此访问通过引用进行:

class A {
public:
    int a(0);
    int b(0);
    int c(0);
    A() {
        a = 1;
        this->b = 2;
        (*this).c = 3;
        std::cout << a << " " << b << " " << c << '\n'; // prints 1 2 3
    }
};

如果它是副本,则无法设置成员变量的值。每次您更改原点的值时,它都是参考,而不是副本。