本节课我们来看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
void swap(int *ap, int *bp)
{
int temp = *ap;
*ap = *bp;
*bp = temp;
}
<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;
可以发现引用可能比指针更加好用, 但是请注意一点, 就是引用一旦确认引用对象后就不能在改变了。
接下来看看结构体和类, 在底层中结构体和类都是以相同的方式存储在内存中的, 在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);
对于函数minky来说, c++会默认传入一个对象的地址作为参数, 因此在内存中参数分布如下所示:
就我个人理解, c++在对于类的实现本质上与c的结构体+函数的实现是一致的, 只不过c++帮助我们屏蔽了很多细节。例如在之前的c语言版本stack中, 我们需要手动传入结构体的地址给函数, 而c++则默认帮我们实现了。