汇编角度看值传递类对象

首先奉上源代码

class A{
private:
    int i;
public:
    A() {
        std::cout << "default constructor is called" << std::endl;
        i = 0;
    }

    A(int _i): i(_i) {}
    
    A(const A& obj) {
        std::cout << "copy constructor is called" << std::endl;
        i = obj.i;
    }

    A& operator = (const A& obj) {
        std::cout << "assignment constructor is called" << std::endl;
        i = obj.i;
        return *this;
    }

    A (const std::initializer_list<int>& l) {
        std::cout << "initializer_list constructor is called" << std::endl;
        i = *(l.begin());
    }

    int get()const  {
        return i;
    }

    void set(int j) {
        i = j;
    }
};

void foo(A a){
    a.set(0xFF);
 }

int main() {
    A a(3);
    foo(a);
    return 0;

}

对于main函数中foo(a)这个函数调用,生成的汇编如下:

45	    foo(a);
   0x00005562b9bc5219 <+44>:	lea    rdx,[rbp-0x10]
   0x00005562b9bc521d <+48>:	lea    rax,[rbp-0xc]
   0x00005562b9bc5221 <+52>:	mov    rsi,rdx
   0x00005562b9bc5224 <+55>:	mov    rdi,rax
   0x00005562b9bc5227 <+58>:	call   0x5562b9bc52d6 <A::A(A const&)>
   0x00005562b9bc522c <+63>:	lea    rax,[rbp-0xc]
   0x00005562b9bc5230 <+67>:	mov    rdi,rax
   0x00005562b9bc5233 <+70>:	call   0x5562b9bc51c9 <foo(A)>

从以上汇编可以明显看到,如果foo()的形参是一个值类型的话,首先调用copy构造函数生成一个实参对象的副本,然后把这个副本的地址传递给函数调用,记住,是副本的地址!

以下是foo的汇编,

Dump of assembler code for function foo(A):
39	void foo(A a){
   0x00005562b9bc51c9 <+0>:	endbr64 
   0x00005562b9bc51cd <+4>:	push   rbp
   0x00005562b9bc51ce <+5>:	mov    rbp,rsp
   0x00005562b9bc51d1 <+8>:	sub    rsp,0x10
   0x00005562b9bc51d5 <+12>:	mov    QWORD PTR [rbp-0x8],rdi

40	    a.set(0xFF);
   0x00005562b9bc51d9 <+16>:	mov    rax,QWORD PTR [rbp-0x8]
   0x00005562b9bc51dd <+20>:	mov    esi,0xff
=> 0x00005562b9bc51e2 <+25>:	mov    rdi,rax
   0x00005562b9bc51e5 <+28>:	call   0x5562b9bc5322 <A::set(int)>

41	 }
   0x00005562b9bc51ea <+33>:	nop
   0x00005562b9bc51eb <+34>:	leave  
   0x00005562b9bc51ec <+35>:	ret    

End of assembler dump.

其实也很好理解,如果要原模原样的copy一个类对象的值的话,效率是非常低下的, 也非常浪费栈空间。

posted @ 2024-11-13 09:40  风冷无霜  阅读(3)  评论(0编辑  收藏  举报