[c/c++]指针(4)
现在讲一下指针的主要用途和常见错误。
[用途]
1.用作形参
首先,常见新手写交换函数:
void swap(int a,int b){
int t = a;
a = b;
b = t;
}
主函数里调用一下试试,看看a,b的值有没有改变?
#include<iostream>
#include<stdlib.h>
using namespace std;
void swap(int,int);
int main(){
int a = ;
int b = ;
swap(a,b);
cout<<a<<" "<<b;
return ;
}
void swap(int a,int b){
int t = a;
a = b;
b = t;
}
运行结果就不公布了,对于新手,有木有发现什么不对的地方?
是什么原因造成这个结果的呢?应该是内存地址吧,要同一内存地址修改其中一个的值
才会改变另一个的值,那来验证一下:
#include<iostream>
#include<stdlib.h>
using namespace std;
void swap(int,int);
int main(){
int a = ;
int b = ;
cout<<"address in main: &a = "<<&a<<" &b = "<<&b<<endl;
swap(a,b);
cout<<a<<" "<<b;
return ;
}
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
看来确实是这样的。。。
那么要是swap和main函数中a,b两变量的内存地址相等,可以用指针来完成
#include<iostream>
#include<stdlib.h>
using namespace std;
void swap(int*,int*);
int main(){
int a = ;
int b = ;
cout<<"address in main: &a = "<<&a<<" &b = "<<&b<<endl;
swap(&a,&b);
cout<<a<<" "<<b;
return ;
}
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 = 0x22fedc &b = 0x22fed8
(注:如果读者知道,其实还有一种代码写起来可读性比指针高,错误率比指针低的方式,就是用引用&)
2.提高运行速度
随便打了篇代码来做实验,第一个seta函数是不用指针给结构体中的数据赋值,第二个setb函数时用指针给
结构体中的数据赋值
#include<iostream>
#include<ctime>
using namespace std;
struct a{
int a[];
int len;
}c;
a seta(a b,int index,int val){
b.a[index] = val;
return b;
}
a setb(a *b,int index, int val){
b->a[index] = val;
return *b;
}
int main(){
clock_t begin = clock();
for(int i = ;i < ;i++)
c = seta(c, i, i);
clock_t end = clock(); clock_t begin1 = clock();
for(int i = ;i < ;i++)
c = setb(&c, i, i);
clock_t end1 = clock(); cout<<"非指针:"<<(end - begin)<<"ms"<<endl;
cout<<"指针 :"<<(end1 - begin1)<<"ms"<<endl;
return ;
}
运行结果(鉴于我家渣机外加开了很多程序所以运行地很慢):
非指针:1781ms
指针 :672ms
有木有发现什么明显的差距,稍微微调一下,把setb函数改成:
void setb(a *b,int index, int val){
b->a[index] = val;
}
然后编译运行,神奇的事发生了:
非指针:1078ms
指针 :0ms
是不是很神奇?
想知道这是为什么吗?
因为在结构体传递的时候是值传递,又因为数组很大,所以要拷贝过来,赋值的
时候也是需要拷贝,所以非常消耗时间,而指针是地址传递,相当于是一个要复制
一个数组,而另一个却只用复制4字节的数据就完成了一样的事
其实还可以比较一下,指针和引用的时间消耗:
#include<iostream>
#include<ctime>
using namespace std;
struct a{
int a[];
int len;
}c;
void seta(a& b,int index,int val){
b.a[index] = val;
}
void setb(a *b,int index, int val){
b->a[index] = val;
}
int main(){
clock_t begin = clock();
for(int i = ;i < ;i++)
seta(c, i, i);
clock_t end = clock(); clock_t begin1 = clock();
for(int i = ;i < ;i++)
setb(&c, i, i);
clock_t end1 = clock(); cout<<"引用:"<<(end - begin)<<"ms"<<endl;
cout<<"指针:"<<(end1 - begin1)<<"ms"<<endl;
return ;
}
结果可以多运行几次,不行可以加大数据,指针和引用貌似时间消耗差不多,不过引用写起来是要
比指针简单一些,像这样也就最多有10ms
3.用于各种数据结构
例如各种树结构,链表等
4.给指定内存存储的数据赋值(在开发操作系统时,这貌似是允许的)
5.通过new、malloc等来省内存
[常见错误]
1.空内存地址
当一个指针的值等于 0x00(NULL,windef.h下定义)时,这必定是一个空内存,如果用到了访问*,程序直接崩溃,访问无效内存
还有就是与其它程序或者系统的专用内存段等冲突,也会导致程序崩溃,这就是因为即使有时候数组下标超了一点点时也可能不会崩溃
的原因
2.访问用过delete或free()后的指针
3.滥用指针,导致浪费内存
另外指针经常也很难看懂,比如,你能一样告诉我这是什么类型的指针吗?(下)
typedef char*const(*p)(long long);
总之指针还得多使用,能用熟最好,不然最好不用,用引用去代替它,
如果到什么开发什么程序的时候,程序崩溃了,都不知道为什么,那
可就糟了
[c/c++]指针(4)的更多相关文章
- TODO:Golang指针使用注意事项
TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...
- enote笔记法使用范例(2)——指针(1)智能指针
要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...
- C++虚函数和函数指针一起使用
C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...
- C++11 shared_ptr 智能指针 的使用,避免内存泄露
多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...
- c 数组与指针的使用注意事项
数组变量和指针变量有一点小小的区别 所以把数组指针赋值给指针变量的时候千万要小心 加入把数组赋值给指针变量,指针变量只会包含数组的地址信息 而对数组的长度一无所知 相当于指针丢失了一部分信息,我们把这 ...
- Marshal.Copy将指针拷贝给数组
lpStatuss是一个UNITSTATUS*的指针类型实例,并包含SensorDust字段 //定义一个数组类型 byte[] SensorDust = new byte[30] //将指针类型拷贝 ...
- C++智能指针
引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...
- EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针
一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...
- 智能指针shared_ptr的用法
为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...
- 智能指针unique_ptr的用法
unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...
随机推荐
- Ubuntu 14.04 使用速度极快的Genymotion 取代蜗牛速度的原生AVD模拟器
Ubuntu 14.04 使用速度极快的Genymotion 取代蜗牛速度的原生AVD模拟器 2014-5-29阅读4045 评论0 默认的AVD的速度可谓奇慢无比,一番搜索最后找到了 ...
- 正向代理 forward proxy、反向代理 reverse proxy、透明代理 transparent proxy nginx反向代理原理和配置讲解 防止外部客户机获取内部内容服务器的重定向 URL 缓存命中
[大型网站技术实践]初级篇:借助Nginx搭建反向代理服务器 - Edison Chou - 博客园http://www.cnblogs.com/edisonchou/p/4126742.html 图 ...
- RESTful URL设计指南(转)
add by zhj: <RESTful Web Services Cookbook>这本书详细介绍了RESTFUL API的设计. 一般来说,一个好的URL,简单明了.这里有一个问题,对 ...
- python中url解析 or url的base64编码
目录 from urllib.parse import urlparse, quote, unquote, urlencode1.解析url的组成成分:urlparse(url)2.url的base6 ...
- requests的post请求:百度翻译
import json import requests class Trans(object): def __init__(self, juzi): self.juzi = juzi self.bas ...
- Linux(CentOS)安装Mysql数据库
1.需要mysql-linux安装包 本次使用mysql-5.7.17-linux-glibc2.5-x86_64.tar.gz进行安装 2.将此安装包上传至linux服务器 上传路径为:/usr ...
- 002-redis-数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). 使用桌面工具查看,默认有16个库,Redis支持多 ...
- 1.keras实现-->自己训练卷积模型实现猫狗二分类(CNN)
原数据集:包含 25000张猫狗图像,两个类别各有12500 新数据集:猫.狗 (照片大小不一样) 训练集:各1000个样本 验证集:各500个样本 测试集:各500个样本 1= 狗,0= 猫 # 将 ...
- java selenium webdriver处理JS操作窗口滚动条
未经作者允许,禁止转载!!! java selenium webdriver处理JS操作窗口滚动条 java selenium webdriver处理JS操作窗口滚动条 import org.open ...
- 让声音更清晰,用PR去掉视频中的噪音
Premiere V7.0没有支持当前文件类型的输入源的问题 25 我是新手,把DVD影片放到电脑里,显示的是VOB文件,导入类型显示的是所有支持格式,于是我就点击了VOB文件,但是说没有支持当前文件 ...