函数的指针
一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址。我们可以把函数的这个首地址赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。
函数指针的定义形式为:
returnType (*pointerName)(param list);
returnType 为函数返回值类型,pointerNmae 为指针名称,param list 为函数参数列表。参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称,这一点和函数原型非常类似。
用指针来实现对函数的调用:
#include <stdio.h> //返回两个数中较大的一个 int max(int a, int b) { return a>b ? a : b; } int main() { int x, y, maxval; //定义函数指针 int (*pmax)(int, int) = max; //也可以写作int (*pmax)(int a, int b) printf("Input two numbers:"); scanf("%d %d", &x, &y); maxval = (*pmax)(x, y); printf("Max value: %d\n", maxval); return 0; }
结构体和指针
结构体指针有特殊的语法: -> 符号
如果p是一个结构体指针,则可以使用 p ->【成员】 的方法访问结构体的成员
typedef struct { char name[31]; int age; float score; }Student; int main(void) { Student stu = {"Bob" , 19, 98.0}; Student*ps = &stu; ps->age = 20; ps->score = 99.0; printf("name:%s age:%d ",ps->name,ps->age); return 0; }
const 和 指针
指向常量的指针,值不能改变,指向可改变
常指针值能改变,指向不可改变
指向常量的常指针,都不能改变
#include <stdio.h> int main() { // 1 可改变指针 const int a = 10; int *p = &a; *p = 1000; printf("*p = %d\n", *p); // 2 可改变指针 const b = 10; int *pb = &b; pb = p; printf("*pb = %d\n", *pb); // 3 const c = 10; int * const pc = &c; *pc = 1000; //pc = pb;不能改变 //4 const d = 10; const * int const pd = &d; //*pd = 1000; 不能改变 printf("\n"); return 0; }
深拷贝和浅拷贝
如果2个程序单元(例如2个函数)是通过拷贝 他们所共享的数据的 指针来工作的,这就是浅拷贝,因为真正要访问的数据并没有被拷贝。如果被访问的数据被拷贝了,在每个单元中都有自己的一份,对目标数据的操作相互 不受影响,则叫做深拷贝。
#include <iostream> using namespace std; class CopyDemo { public: CopyDemo(int pa,char *cstr) //构造函数,两个参数 { this->a = pa; this->str = new char[1024]; //指针数组,动态的用new在堆上分配存储空间 strcpy(this->str,cstr); //拷贝过来 } //没写,C++会自动帮忙写一个复制构造函数,浅拷贝只复制指针,如下注释部分 //CopyDemo(CopyDemo& obj) //{ // this->a = obj.a; // this->str = obj.str; //这里是浅复制会出问题,要深复制 //} CopyDemo(CopyDemo& obj) //一般数据成员有指针要自己写复制构造函数,如下 { this->a = obj.a; // this->str = obj.str; //这里是浅复制会出问题,要深复制 this->str = new char[1024];//应该这样写 if(str != 0) strcpy(this->str,obj.str); //如果成功,把内容复制过来 } ~CopyDemo() //析构函数 { delete str; } public: int a; //定义一个整型的数据成员 char *str; //字符串指针 }; int main() { CopyDemo A(100,"hello!!!"); CopyDemo B = A; //复制构造函数,把A的10和hello!!!复制给B cout <<"A:"<< A.a << "," <<A.str << endl; //输出A:100,hello!!! cout <<"B:"<< B.a << "," <<B.str << endl; //输出B:100,hello!!! //修改后,发现A,B都被改变,原因就是浅复制,A,B指针指向同一地方,修改后都改变 B.a = 80; B.str[0] = 'k'; cout <<"A:"<< A.a << "," <<A.str << endl; //输出A:100,kello!!! cout <<"B:"<< B.a << "," <<B.str << endl; //输出B:80,kello!!! return 0; }
根据上面实例可以看到,浅复制仅复制对象本身(其中包括是指针的成员),这样不同被复制对象的成员中的对应非空指针会指向同一对象,被成员指针引用的对象成为共享的,无法直接通过指针成员安全地删除(因为若直接删除,另外对象中的指针就会无效,形成所谓的野指针,而访问无效指针是危险的;
除非这些指针有引用计数或者其它手段确保被指对象的所有权);而深复制在浅复制的基础上,连同指针指向的对象也一起复制,代价比较高,但是相对容易管理。