cs107 编程范式(十)

219 阅读2分钟

本节课我们来看c++与c汇编代码之间的关系

void foo() 
{
    int x;
    int y;
    
    x = 11;
    y = 17;
    swap(&x, &y);
}
SP = SP - 8
M[SP + 4] = 11
M[SP] = 17
R1 = SP
R2 = SP + 4
SP = SP - 8
M[SP] = R2
M[SP + 4] = R1
CALL <swap>
SP = SP + 8
SP = SP + 8
RET

1.PNG

void swap(int *ap, int *bp) 
{
    int temp = *ap;
    *ap = *bp;
    *bp = temp;
}

新建 Microsoft PowerPoint 演示文稿.png

<swap>:
SP = SP - 4
R1 = M[SP + 8]
R2 = M[R1] 
M[SP] = R2
R1 = M[SP + 12]
R2 = M[R1]
R3 = M[SP + 8]
M[R3] = R2
R1 = M[SP]
R2 = M[SP + 12]
M[R2] = R1
SP = SP + 4
RET

c++版swap函数

void swap(int &a, int &b) 
{
    int temp = a;
    a = b;
    b = temp;
}

虽然这里使用引用的方式来进行参数传递, 但是在底层的实现中汇编代码与c语言指针版本一致, 这是因为c++编译器会在底层进行处理,对引用的任何操作都产生解指针的效果。

再看看下面的代码

int x = 17;
int y = x;
int& z = y;

捕获.PNG

可以发现引用可能比指针更加好用, 但是请注意一点, 就是引用一旦确认引用对象后就不能在改变了。

接下来看看结构体和类, 在底层中结构体和类都是以相同的方式存储在内存中的, 在c++中结构体是可以定义方法的, 在c++中结构体和类唯一的区别就在于, 对于类来说默认的访问修饰符是private的, 而对于结构体来说默认的访问修饰符是public。

class binky
{
public:
    int dunky(int x, int y);
    char* minky(int *z) {
        int w = *z;
        return slinky + dunky(winky, winky);
    }
private:
    int winky;
    char* binky;
    char slinky[8];
};

int n = 17;
binky b;
b.minky(&n);    // binky::minky(&b, &n);

捕获1.PNG

对于函数minky来说, c++会默认传入一个对象的地址作为参数, 因此在内存中参数分布如下所示:

捕获2.PNG

就我个人理解, c++在对于类的实现本质上与c的结构体+函数的实现是一致的, 只不过c++帮助我们屏蔽了很多细节。例如在之前的c语言版本stack中, 我们需要手动传入结构体的地址给函数, 而c++则默认帮我们实现了。