先要知道的一点:
C++中,成员变量是属于对象的,而函数是属于类的。
怎么看这件事情呢?
#include <iostream>
using namespace std;
struct Data{
int x = 10;
int y() { return 20; }
};
int main()
{
Data* p=NULL; // 不用 new 创建指针
cout<<p->x<<endl; //抛出异常
cout<<p->y()<<endl; //程序能正常输出20
return 0;
}
//以下文字引用自:https://blog.csdn.net/qq_30366449/article/details/78402419
成员函数和普通函数没有本质什么区别,都是直接调用函数的,只是比普通函数多了一个 this 指针而已。如果成员函数里面没有使用这个 this 指针(也就是没有使用任何成员变量),那么 this 指针的值为多少就无所谓了,不管他是随机值或是 NULL.
只用通过指针调用虚函数才会通过对象的虚函数表去查找函数的地址,这时指针无效就会出问题了。
在上面代码中,int* p;到底有没有在堆空间开辟一个4字节大小的内存空间呢?
没有,这是在栈内定义的一个指针,所以是在栈内开辟了一个4字节大小的内存空间(用来放指针变量了)。
与此对应的,int* p = new int;是在栈上开辟了4个字节放指针,又在堆上开辟了4个字节(准备)放int变量函数之所以会调用成功,是因为利用指针调用类的成员函数时,只跟指针的类型有关,而与其所指内容无关,也就是说只要指针类型是这个类的指针,那就可以用它来调用这个类的成员函数。如果这个函数做的事情跟类对象无关,就像你只返回一个常数,那这个函数看起来是正常运行的,但如果在类里访问了类的成员变量(比如返回x),那就会出错,因为此时要根据指针所指的内容去访问对应的成员变量,而指针实际上没有指向正确的地方,所以会出现内存访问错误。
------------------------------------------------------------------------
那么……this指针是啥呢?
#include <iostream>
using namespace std;
class A
{
public:
void f();
int m_a;
};
void A::f()
{
m_a = 20;
cout << m_a << endl;
}
struct B
{
int m_b;
};
void ff(struct B* p)
{
p->m_b = 20;
cout << p->m_b << endl;
}
int main()
{
A a;
B b;
a.m_a=10;
cout << a.m_a << endl;
a.f();
ff(&b);
return 0;
}
当我们在a.f()的时候,他会知道我们调用的是哪个对象。
实际上的f()函数就和那个struct B一样,但传入的那个对象的地址。
所以上述代码中的 f() 的函数原型为:
我们来想办法看一下这个东西:
//#include <iostream>
//using namespace std;
#include <stdio.h>
class A
{
public:
void f();
int m_a;
};
void A::f()
{
m_a = 20;
printf("A::f()--&m_a = %p\n",&m_a);
}
int main()
{
A a;
a.m_a=10;
printf("&a=%p\n",&a);
a.f();
return 0;
}
//我们也可以在f()中输出以下this的地址:
printf("this -- %p\n",this);
地址是一样的,这就说明了以上的。
this指针:是一个隐藏的指针(the hidden parameter)
· 成员函数最终会被编译成与对象无关的普通函数。除了成员变量,丢失所有信息
· 相同类型的不同对象共享同一份成员函数代码。因此编译时在成员函数中添加一个隐藏函数,将当前调用对象收地址传入,用来关联成员函数和成员变量,这就是this指针
· C++关键字,const指针,在类的成员函数,构造函数和析构函数中,对所有成员的访问,都是通过this指针
以下为我的this的笔记:
class A{};
class Student
{
public:
Student(string name,int age,char gender):m_name(name),m_age(age),m_gender(gender){}
~Student(){}
void print()
{
cout << this->m_name << "," << this->m_age << "," << this->m_gender <<endl;
}
private:
string m_name; //名字
int m_age; //年龄
char m_gender; //性别 1 GG| 2 MM
};
int main()
{
A a1,a2;
cout << sizeof(a1) << endl; //空类 用一个char标示
cout << sizeof(string) <<endl; // 24 string在vs下是28,在xcode是24
// string是以指针指向字符串,所以不论存多少内容都是原大小
Student stu("ahoj",10,'G');
cout << sizeof(stu) <<endl; // 24(string) + 4(int) + 4(char) 内存对齐
// 对象的大小是成员变量的大小
stu.print();
/*编译器眼中
this指针,当前调用对象的指针
stu.print(&stu);
void print(Student* const this)
{
cout << this->m_name << "," << this->m_age << "," << yhis->m_gender <<endl;
}*/
int a = 10;
int *p = new int(20);
cout << &a << " " << p << endl;
// 堆区、栈区、代码区 内存地址从低到高
return 0;
}