【摘要】
指针可以指向变量、数组、字符串、函数、甚至结构体。即指针可以指向不同数据对象。指针问题 包括 常量指针、数组指针、函数指针、this指针、指针传值、指向指针的指针 等。主要知识点包括:1.指针与引用在概念上的三个区别及其在const、sizeof、自增运算上的差异;2.熟记经典swap函数的指针实现与引用实现,并能反映输出错误的两个函数的思想弊端;3.熟记GetMem函数的错误形式以及错误产生的原因;4.比较数组、指针与静态变量作为函数返回值的差异;5.str、*str以及&str三者的关系;6.指针继承复指向中虚函数、实函数及变量间的关系;7.写出const指针,指向const的指针,指向const的const指针;8.分析高维数组指针与高维数组在取址上的差别;9.区分悬浮指针与空指针;10.new和malloc的常见问题,本质区别,为什么产生new,为什么不提出malloc;11.this指针3个点,为什么会有this,this什么时候用,this怎么传给函数的;12.句柄和智能指针。考点:指针与引用的区别
int &ref;
// 错误,引用不能为空且需要同时初始化,因此错误!
int *p = 5;
// 错误,指针位置向实际内存空间,赋值之后不知道存放的地址,没有指向,因此错误!
int *ptra,*ptrb;
int ptra = *ptrb;
// 错误,指针位置向实际内存空间,赋值之后不知道存放的地址,因此错误!
const int num;
// 错误,const 常量赋值必须同时初始化,因此错误!
考点:经典的 swap(int &a,int &b)函数void GetMemA(char *p,int num)
{
p = (char*)malloc(sizeof(char)*num);
}
void GetMemB(char **p,int num)
{
*p = (char*)malloc(sizeof(char)*num);
}
【解析】
因为,函数不能传值只能传址,所以,在函数内采用指针申请内存空间(即,void GetMem(char *p,int num))是不会成功的。那么为实现空间申请我们应该采用指向指针的指针(即,void GetMem(char **p,int num))。
假设,在 main() 函数中,变量 p 地址为 1 指向地址为 2(可以想象成变量 p 值为 2),*p 地址为 2 指向地址为 3(可以想象成变量 *p 值为 3),**p 地址为 3 存放一 char 型变量。
在 void GetMemA(char *p,int num)中,暂时称函数变量为 GetMemA.p 吧,很明显 GetMemA.p 是一个地址,指向一个 char 型变量。函数申请栈区进入函数后,GetMemA.p 地址为 4 ,指针变量获取一块长度为 num 的 char 型内存空间。函数调用结束,弹栈销毁 变量GetMemA.p 及其申请的空间,那么,主函数中的变量 p 没有得到任何改变;
在 void GetMemB(char **p,int num)中,暂时称函数变量为 GetMemB.*p 吧,很明显 GetMemB.*p 是一个地址,指向一个 char 型变量。函数申请栈区进入函数后,GetMemB.*p 地址为 5 ,指针变量获取一块长度为 num 的 char 型内存空间。函数调用结束,弹栈销毁 变量 GetMemB.p 及其申请的空间(注意,这里是变量 GetMemB.p 而不是 变量 GetMemB.*p),那么,GetMemB.*p 自然而然的保留了申请得到的内存空间,主函数中的变量 p 没有得到任何改变,而 *p 获得了一段长度为 num 的 char 型内存空间;
当然,函数还可写成这样直接返回内存空间。
char* GetMemC(char *p,int num)
{
p = (char*)malloc(sizeof(char)*num);
}
【整型数据的源码传递】
#include
using namespace std;
void GetMemory2(int *z)
{
*z=5;
};
int main()
{
int v;
GetMemory2(&v);
cout << v << endl;
return 0;
}
【注】char *strA()
{
char str[] = "hello world";
return str;
}
解析:char *strA()
{
char *str = "hello world";
return str;
}
首先要搞清楚char *str 和 char str[] :char *strA()
{
static char str[] = "hello world";
return str;
}
通过static开辟一段静态存贮空间。
【另】
char *str = “hello”;#include ...
class A{ ... };
class B{ ... };
int main( )
{
A a;
B *pb = (B*)(&a);
}
【解析】#include ...
int main( )
{
int *ptr;
ptr = (int*)0x8000;
*ptr = oxaabb;
}
【解析】#include
using namespace std;
struct S
{
int i;
int *p;
}
main( )
{
S s;
int *p = &s.i;
p[0] = 1;
p[1] = 5;
cout<<"s 的地址 \t"<<&s<
【代码输出】
s 的地址 0018FF40
s.i 的地址 0018FF40
p 的值 0018FF40
p[0] 的地址 0018FF40
s.p 的地址 0018FF44
p[1] 的地址 0018FF44
s.i 的值 1
s.p 的值 00000005
*s.p 的值 报错
s.*p 的值 报错
&s.*p 的值 报错
************************
执行s.p = p; 之后
************************
s 的地址 0018FF40
s.i 的地址 0018FF40
p 的值 0018FF40
p[0] 的地址 0018FF40
s.p 的值 0018FF40
s.p 的地址 0018FF44
s.p[0] 的值 1
s.p[1] 的值 1638208
p[1] 的地址 0018FF44
p[0] 的值 1
p[1] 的值 1638208
************************
执行s.p[1] = 1; 之后
************************
s.p = 00000001
s.p+1 = 00000005
Press any key to continue
【代码分析】int *p = &s.i;
// 等价于 p = &p[0] = &s = &s.i
// 且还有 p+1 = &p[1] = &s+1 = &s.i+1 = &s.p
s.p = p;
// 要知道 (s.*p) = s.p = p
// 等价有 *(p+1) = *&p[1] = *&s+1 = *&s.i+1 = *&s.p = p
// 简化得 *(p+1) = p[1] = s+1 = s.i+1 = s.p = p
// 已知道 p = &p[0] = s.p = &s.p[0]
// 所以有 &p[0] = p[1] 和 &s.p[0] = s.p[1]
s.p[1] = 1
// 此时再给,s.p[0]或者p[0]赋值,等价于在内存地址为 1 的空间写入变量。
// 所以,此句暂时不会报错,一旦对指向地址赋值,就会导致程序崩溃。
考点:各种类型的指针表示
注
函数指针声明方式int *ptr(int,int) = &max;
详见:
C++ 高维指针数组 与 高维数组指针(一)
C++ 高维指针数组 与 高维数组指针(二)
C++ 数组指针 指针数组 以及 函数指针 指针函数
详址:
http://blog.csdn.net/u013630349/article/details/44998689
http://blog.csdn.net/u013630349/article/details/44195523
http://blog.csdn.net/u013630349/article/details/45098899
int a[] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d %d", *(a+1), *(ptr-1));
说明:*(a+1) 直接就为2 简单&a+1 由于本身a就为数组名也就是指针,加上& 相当于双指针 也就相当于**(a+1) 所以加1 就是数组整体加一行,ptr指向a的第6个元素,所以*(ptr-1)为5
详见:C++ 数组指针 指针数组 以及 函数指针 指针函数
详址:http://blog.csdn.net/u013630349/article/details/45098899
悬浮指针为申请了内存,经过一系列操作,释放内存后的指针。指针虽不再指向固定内存,但是,指针还是存在,且指向随机区域,此时对指针操作十分危险的。
malloc free new delete 的区别、比较、分析
详见:C++ 中 malloc/free 与 new/delete 浅析
详址:http://blog.csdn.net/u013630349/article/details/44947255
详见:C++ this 指针 浅析
详址:http://blog.csdn.net/u013630349/article/details/46412485
C++的编译系统只用了一段空间来存放在公共函数代码,在调用各个对象的成员函数时,都要调用这个公共的函数代码