[c/c++]指针(4)

  现在讲一下指针的主要用途和常见错误。



[用途]

1.用作形参

  首先,常见新手写交换函数:

1 void swap(int a,int b){
2     int t = a;
3     a = b;
4     b = t;
5 } 

  主函数里调用一下试试,看看a,b的值有没有改变?

 1 #include<iostream>
 2 #include<stdlib.h>
 3 using namespace std;
 4 void swap(int,int);
 5 int main(){
 6     int a = 2;
 7     int b = 1;
 8     swap(a,b);
 9     cout<<a<<" "<<b;
10     return 0;
11 }
12 void swap(int a,int b){
13     int t = a;
14     a = b;
15     b = t;
16 } 

  运行结果就不公布了,对于新手,有木有发现什么不对的地方?

是什么原因造成这个结果的呢?应该是内存地址吧,要同一内存地址修改其中一个的值

才会改变另一个的值,那来验证一下:

#include<iostream>
#include<stdlib.h>
using namespace std;
void swap(int,int);
int main(){
    int a = 2;
    int b = 1;
    cout<<"address in main: &a = "<<&a<<" &b = "<<&b<<endl;
    swap(a,b);
    cout<<a<<" "<<b;
    return 0;
}
void swap(int a,int b){
    int t = a;
    a = b;
    b = t;
    cout<<"address in swap: &a = "<<&a<<" &b = "<<&b<<endl;
}

运行结果

address in main: &a = 0x22fedc &b = 0x22fed8
address in swap: &a = 0x22fec0 &b = 0x22fec4
2 1

看来确实是这样的。。。

那么要是swap和main函数中a,b两变量的内存地址相等,可以用指针来完成

 1 #include<iostream>
 2 #include<stdlib.h>
 3 using namespace std;
 4 void swap(int*,int*);
 5 int main(){
 6     int a = 2;
 7     int b = 1;
 8     cout<<"address in main: &a = "<<&a<<" &b = "<<&b<<endl;
 9     swap(&a,&b);
10     cout<<a<<" "<<b;
11     return 0;
12 }
13 void swap(int* a,int* b){
14     int t = *a;
15     *a = *b;
16     *b = t;
17     cout<<"address in swap: &a = "<<a<<" &b = "<<b<<endl;
18 } 

运行结果

address in main: &a = 0x22fedc &b = 0x22fed8
address in swap: &a = 0x22fedc &b = 0x22fed8
1 2

(注:如果读者知道,其实还有一种代码写起来可读性比指针高,错误率比指针低的方式,就是用引用&)

2.提高运行速度

  随便打了篇代码来做实验,第一个seta函数是不用指针给结构体中的数据赋值,第二个setb函数时用指针给

结构体中的数据赋值

 

 1 #include<iostream>
 2 #include<ctime>
 3 using namespace std;
 4 struct a{
 5     int a[100000];
 6     int len;
 7 }c;
 8 a seta(a b,int index,int val){
 9     b.a[index] = val;
10     return b;
11 }
12 a setb(a *b,int index, int val){
13     b->a[index] = val;
14     return *b;
15 }
16 int main(){
17     clock_t begin = clock();
18     for(int i = 0;i < 1000;i++)
19         c = seta(c, i, i);
20     clock_t end = clock();
21
22     clock_t begin1 = clock();
23     for(int i = 0;i < 1000;i++)
24         c = setb(&c, i, i);
25     clock_t end1 = clock();
26
27     cout<<"非指针:"<<(end - begin)<<"ms"<<endl;
28     cout<<"指针  :"<<(end1 - begin1)<<"ms"<<endl;
29     return 0;
30 }

运行结果(鉴于我家渣机外加开了很多程序所以运行地很慢):

非指针:1781ms
指针  :672ms

有木有发现什么明显的差距,稍微微调一下,把setb函数改成:

void setb(a *b,int index, int val){
    b->a[index] = val;
}

然后编译运行,神奇的事发生了:

非指针:1078ms
指针  :0ms

是不是很神奇?

想知道这是为什么吗?

  因为在结构体传递的时候是值传递,又因为数组很大,所以要拷贝过来,赋值的

时候也是需要拷贝,所以非常消耗时间,而指针是地址传递,相当于是一个要复制

一个数组,而另一个却只用复制4字节的数据就完成了一样的事

  其实还可以比较一下,指针和引用的时间消耗:

 1 #include<iostream>
 2 #include<ctime>
 3 using namespace std;
 4 struct a{
 5     int a[1000000];
 6     int len;
 7 }c;
 8 void seta(a& b,int index,int val){
 9     b.a[index] = val;
10 }
11 void setb(a *b,int index, int val){
12     b->a[index] = val;
13 }
14 int main(){
15     clock_t begin = clock();
16     for(int i = 0;i < 1000000;i++)
17         seta(c, i, i);
18     clock_t end = clock();
19
20     clock_t begin1 = clock();
21     for(int i = 0;i < 1000000;i++)
22         setb(&c, i, i);
23     clock_t end1 = clock();
24
25     cout<<"引用:"<<(end - begin)<<"ms"<<endl;
26     cout<<"指针:"<<(end1 - begin1)<<"ms"<<endl;
27     return 0;
28 }

  结果可以多运行几次,不行可以加大数据,指针和引用貌似时间消耗差不多,不过引用写起来是要

比指针简单一些,像这样也就最多有10ms

3.用于各种数据结构

  例如各种树结构,链表等

4.给指定内存存储的数据赋值(在开发操作系统时,这貌似是允许的)

5.通过new、malloc等来省内存



[常见错误]

1.空内存地址

  当一个指针的值等于 0x00(NULL,windef.h下定义)时,这必定是一个空内存,如果用到了访问*,程序直接崩溃,访问无效内存

还有就是与其它程序或者系统的专用内存段等冲突,也会导致程序崩溃,这就是因为即使有时候数组下标超了一点点时也可能不会崩溃

的原因

2.访问用过delete或free()后的指针

3.滥用指针,导致浪费内存

另外指针经常也很难看懂,比如,你能一样告诉我这是什么类型的指针吗?(下)

typedef char*const(*p)(long long);

总之指针还得多使用,能用熟最好,不然最好不用,用引用去代替它,

如果到什么开发什么程序的时候,程序崩溃了,都不知道为什么,那

可就糟了

时间: 2024-10-14 14:02:39

[c/c++]指针(4)的相关文章

[c/c++] programming之路(17)、高级指针

一.二级指针 二级指针的作用:1.函数改变外部变量指针2.外挂改变一个指针的值 1 #include<stdio.h> 2 #include<stdlib.h> 3 4 void main(){ 5 int a = 10; 6 int b = 20; 7 int *p1 = &a; 8 int *p2 = &b; 9 int **pp = &p1; 10 printf("%d,", **pp); 11 printf("\n%x,

C++学习笔记----2.4 C++引用在本质上是什么,它和指针到底有什么区别

从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变. 而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量). 在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的: 指针传递参数本质上是值传递的方式,它所传递的是一个地址值.值传递过程中,被调

【转】父类子类指针相互转换问题

1.当自己的类指针指向自己类的对象时,无论调用的是虚函数还是实函数,其调用的都是自己的: 2.当指向父类对象的父类指针被强制转换成子类指针时候,子类指针调用函数时,只有非重写函数是自己的,虚函数是父类的: 3.当指向子类对象的子类指针被强制转换成父类指针的时候,也就是父类指针指向子类对象,此时,父类指针调用的虚函数都是子类的,而非虚函数都是自己的. 将上面三句话总结成一句话就是:当父类子类有同名非虚函数的时候,调用的是转换后的指针类型的函数: 当父类子类有同名虚函数的时候呢,调用的是指针转换前指

C++ Primer 学习笔记与思考_7 void和void*指针的使用方法

(一)void的含义 void的字面意思是"无类型",void差点儿仅仅有"凝视"和限制程序的作用,由于从来没有人会定义一个void变量,让我们试着来定义: void a; 这行语句编译时会出错.提示"illegal use of type 'void'".只是.即使void a的编译不会出错.它也没有不论什么实际意义. void真正发挥的作用在于: (1) 对函数返回的限定: (2) 对函数參数的限定. int f(void); equal t

当this指针成为指向之类的基类指针时,也能形成多态

this指针: 1)对象中没有函数,只有成员变量 2)对象调用函数,通过this指针告诉函数是哪个对象自己谁. 1 #include<iostream> 2 using namespace std; 3 class Shape 4 { 5 public: 6 //void cal_display(Shape* this) 7 void cal_display(){ 8 display(); 9 this->display(); 10 } 11 private: 12 virtual vo

指针x(超简单的x)

指针! 1 #include<cstdio> 2 #include<iostream> 3 4 using namespace std; 5 6 /* 7 相加或者相乘 8 */ 9 10 int main() 11 { 12 int a,b,s,t; 13 cin>>a>>b; 14 int *p; 15 p=&a; 16 int *q; 17 q=&b; 18 s=(*p)+(*q); 19 t=(*p)*(*q); 20 printf(

二重指针实现排序

1 //双指针对十个数排序 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #define N 8 6 //2017.3.5 7 int main() 8 { 9 //初始化数组 赋值N个数 用指针数组指向 10 int num[N]; 11 int *pNum[N]; 12 int **p = NULL; 13 for (int i = 0; i < N; i++) 14 { 15 num[i] = rand() % 100;/

c指针-专题

六---指针 内存和地址怎么理解呢? 机器中有一些位置,每一个位置被称为[字节]/byte,许多现代机器上,每个字节包含8个位.更大内存单位[字],通常包含2个或4个字节组成. 一个字包含4个字节,它的地址是什么? 他仍然只有一个地址,是最左边还是最右边的那个字节的位置,取决于机器. 机器事实-关于整型的起始位置: 在要求边界对齐(boundaryalignment)的机器上,整型存储的起始位置只能是某些特定的字节,通常是2或4的倍数. 变量名和地址关系? 所有高级语言的特性之一,就是通过名字而

智能指针的原理和简单实现

什么是智能指针? 智能指针实质上是一个类,定义一个类来封装资源的分配和释放.这个类的构造函数中传入一个指针,完成资源的分配和初始化.在析构函数中释放传入的该指针,完成资源的释放. 为什么要用智能指针? 智能指针就是智能,自动化的管理指针所指向的动态资源. 例如以下情况:代码中经常会忘记释放动态开辟的内存资源,导致内存泄露. // case1 void Test2() {  int* p1 = new int(2);  bool isEnd = true;  //...  if (isEnd)  

单继承与多继承中的虚函数表和虚函数指针

首先,我们了解一下何为单继承,何为多继承?? 单继承:一个子类只有一个直接父类. 多继承:一个子类有两个或多个直接父类. 单继承中的虚函数表分析: 示例程序: #include <iostream> using namespace std; typedef void(*FUNC)(); class Base { public: virtual void func1() { cout << "Base::func1()" << endl; } virt