c/c++ 复习基础要点01-const指针、指针函数 函数指针、new/delete与malloc/free区别与联系
1. 引用本身是有指针实现的:引用为只读指针
例子:
int d=123;
int& e=d; //引用
int * const e=d; //只读指针,e指向d,不可修改e指向别的变量
2. const修饰指针问题
2.1.指向const对象的指针:
const double *cptr;
const 所限定的是指针所指的对象,而非限定指针为const
例子:
const double ip=3.14; //ip为const型
const double *cptr=&ip;
//cptr不是const型 ,ip不能赋值为一个非const的指针
注意:不能用void*指针保存const对象的地址,而必须使用const void*类型的指针保存const对象的地址。
可以把非const对象的地址赋值给指向const对象的指针(const void *),则不可修改用指向const对象的指针来修改非const变量。
实例:
#include<iostream>
int main()
{
const int a=12;
int * ptr=&a; //error
const int * cptr=&a; //ok
int b=20;
ptr=&b;
cptr=&b;
cout<<b<<endl;
cptr=15; //error
ptr=15; //ok
cout<<b<<endl;
return 0;
}
2.2.const指针(只读指针)
int a=0;
int *constptr=&a;
const指针存放的地址不能修改,初始化后,指针a不能指向其他的对象。
指针a指向一个普通的非constint型对象a,则可使用指针b修改该对象的值。
2.3.指向const对象的const指针
const doubleip=3.14;
const double *const pi=&ip;
指针所指的对象不可改变,对象的值也不可改变
3. 空指针
void * 指针
void*类型可以保存任意类型对象的地址
void*支持的操作:
与另一个指针进行比较;
向函数传递void*指针或者从函数返回void*指针;
给另一个void*指针赋值
不能使用void*指针操作它所指向的对象。
4. 指针函数、函数指针
4.1.指针函数(为函数):
如果一个函数的返回值是指针类型,则称为指针函数。
数据类型 *函数名(形参类表)
{
函数体
}
用指针作为函数的返回值的好处是:可以从被调函数向朱调函数返回大量数据。
不要把指针函数内部的局部变量赋值为指针返回:
例如:
#include<iostream>
usingspacename std;
int *fun();
void main()
{
int *pfr;
pfr=fun();
cout<<"*pfr="<<*pfr<<endl;
}
int *fun()
{
int va;
int *ptr=&va;
*ptr=5;
cout<<"ptr="<<*ptr<<endl;
return ptr; //error 因为函数内的局部变量在函数结束时就注销了,指针ptr将变成悬垂指针。
}
应该:
#include<iostream>
using spacename std;
int *fun();
void main()
{
int *pfr;
pfr=fun();
cout<<"*pfr="<<*pfr<<endl;
}
int *fun()
{
int *pfr=new int;
*pfr=5;
cout<<"*pfr="<<*pfr<<endl;
return ptr;
}
4.2.函数指针:
指针不仅可以指向变量,还可以指向函数,指向函数的指针称为函数指针。
数据结构 (*指针名)(形参类表);
数据类型代表指针所指向函数的返回类,形参列表是指针所指向函数的形参列表。
列如:
int (*fptr)(int,int);
定义函数指针后,就可以为它赋值,使它指向某个特定的函数:
函数指针名=函数名;
例子:
#include<iostream>
using spacename std;
float areaofRectangle(float width,floatheight);
float areaofTriangle(float heml,floatheight);
void main()
{
float (*fptr)(float,float);
float area,worh,height;
cout<<"请输入矩形的高和宽:";
cin>>worh>>height;
fptr=areaofRectangle;
area=fptr(worh,height);
cout<<"举行面积为:"<<area<<endl;
cout<<"请输入三角形的底和高:";
cin>>worh>>height;
fptr=areaofTriangle;
area=fptr(wroh,height);
cout<<"三角形面积为:"<<area<<endl;
}
float areaofRectangle(float width,floatheight)
{
return width*height;
}
float areaofTriangle(float heml,float height)
{
return (heml*height)/2;
}
5. new delete 与 malloc free 的区别于联系
相同点:都是用于申请动态内存和释放内存
不同点:
(1) 操作对象有所不同。
malloc与free是c语言的标准库函数,new/delete是c++的运算符。对于非内部数据类型的对象而言,光用malloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数任务强加malloc/free。
(2) 用法上也有所不同。
函数malloc的原型如下:
void * malloc(size_t size);
用malloc申请一块长度为length的整数类型的内存,如下:
int * p=(int)malloc(sizeof(int)*length);
我们应该把注意力集中在两个要素上:
1. malloc返回值的类型是void*,所以在调用malloc时要显示地进行类型的转换,将void* 转换成所需要的指针类型。
2. malloc函数本身并不识别要申请的内存是什么类型,它只关心内存的总的字节数。
函数free的原型如下:
void free(void * memblock);
为什么free函数不像malloc函数那样复杂呢?这是因为指针p的类型以及它所指的内存的容量事先都是知道,语句free(p)能正确地释放内存。如果p是NULL指针,那么free对p无论做多少次操作都不会出问题。如果p不是NULL指针,那么free对p连续操作两次就会导致程序运行错误。
new/delete的使用要点:
运算符new使用起来要比函数malloc简单多了,例如:
int *p1=(int)malloc(sizeof(int)*length);
int *p2=new int[length];
这是因为new内置了sizeof、类型转换盒类型安全检查功能。对于非内部数据类型的对象而言,new在创建动态对象的同时完成了初始化工作。如果对象有多个构造函数,那么new的语句也可以有多种形式。
如果用new创建对象数组,那么只能使用对象的无参构造函数。
Obj *objects = newObj[100]; //创建100个动态对象
不能写成
Obj * objects = newObj[100](1); //创建100个动态对象的同时赋值初值1
在用delete释放对象数组时,留言不要丢了符号[]。
delete []objects; //正确的用法
delete objects; //错误的用法
后者相当于delete objects[0],漏掉了另外99个对象。(objects是数组首地址)
再谈二者区别:
1. new自动计算需要分配的空间,而malloc需要手工计算字节数。
2. new是类型安全的,而malloc不是,比如:
int * p = newfloat[2]; //编译时指出错误
int * p =malloc(2*sizeof(float)); //编译时无法指出错误
3. new运算符由两步构成,分别是new 和 调用对象的构造函数
new对应malloc,new调用时将调用要分配的类型的对象的构造函数,而malloc不能。
在delete时,delete调用了释放内存的对象的析构函数,而free不能。
所以我们不要用malloc/free来完成动态对象的内存管理,应该使用new/delete。由于内部数据类型的“对象”没有构造与析构过程,对它们而言malloc/free和new/delete是等价的。
二者的联系:
既然new/delete的功能完全覆盖了malloc/free,为什么c++还要保留malloc/free呢?因为c++程序经常要调用c函数,erc程序只能使用malloc/free管理动态内存。如果使用free释放new创建的动态对象,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放malloc申请的动态内存,理论上程序不会出错,但该程序的可读性很差。
所以new/delete、malloc/free必须配对使用。
c/c++ 复习基础要点01-const指针、指针函数 函数指针、new/delete与malloc/free区别与联系的更多相关文章
- c++复习基础要点02 虚函数与模板 与static inline是否共存
1. 虚函数能否定义为模板函数 当一个类有虚函数时,它一定有一个虚表,用来纪录每个虚函数的实际地址.这也就是说这个虚表的大小是在编译期就确定了的.有多少个虚函数,虚表就纪录几个. ...
- c\c++复习基础要点08--c++单例模式
单例模式有许多种实现方法,在c++中,甚至可以直接用一个全局变量做到这一点,但是这样的代码显得不优雅.使用全局对象能够保证方便地访问实例,但是不能保证只声明一个对象——也就是说除了一个全局实例外,仍然 ...
- c\c++复习基础要点16----枚举类型
枚举类型: 语法格式: enum 枚举类型名 {变量值列表}; 例如: enum Weekday{sun, mon, tue, wed, thu, fri, set}; 声明了枚举类型后,就可以定义 ...
- 【C++自我精讲】基础系列二 const
[C++自我精讲]基础系列二 const 0 前言 分三部分:const用法.const和#define比较.const作用. 1 const用法 const常量:const可以用来定义常量,不可改变 ...
- 小猪猪C++笔记基础篇(六)参数传递、函数重载、函数指针、调试帮助
小猪猪C++笔记基础篇(六) ————参数传递.函数重载.函数指针.调试帮助 关键词:参数传递.函数重载.函数指针.调试帮助 因为一些事情以及自己的懒惰,大概有一个星期没有继续读书了,已经不行了,赶紧 ...
- [C++ Primer Plus] 第7章、函数(一)程序清单——递归,指针和const,指针数组和数组指针,函数和二维数组
程序清单7.6 #include<iostream> using namespace std; ; int sum_arr(int arr[], int n);//函数声明 void ma ...
- const关键字与数组、指针
目录 const关键字 const修饰数组 const修饰指针 用两个const修饰指针 @ 开始回顾C基础知识.C中使用指针是很危险的事情,一个不慎就会造成程序崩溃,因此对于传入函数的参数进行保护就 ...
- 034 01 Android 零基础入门 01 Java基础语法 04 Java流程控制之选择结构 01 流程控制概述
034 01 Android 零基础入门 01 Java基础语法 04 Java流程控制之选择结构 01 流程控制概述 本文知识点:Java中的流程控制相关概念的认识 三大流程控制语句结构的简介 顺序 ...
- JavaScript基础第01天笔记
JavaScript基础第01天 1 - 编程语言 1.1 编程 编程: 就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程. 计算机程序: 就是计算机所执行的一系列的 ...
随机推荐
- ADT下载地址整理
參考以下文章 http://developer.android.com/tools/sdk/eclipse-adt.html 整理了官网的下载地址 http://dl.google.com/andro ...
- ASP.NET MVC Controller接收ajax post方式发送过来的json对象或数组数据
本例旨在说明我的一种Controller接收ajax提交(POST)过来的json对象或数组信息的方式,感觉应该有更好的方式,欢迎提出宝贵意见. JSON.stringify(jsonObj)不支持I ...
- UIButton上图片和文字的位置调整
UIButton 上默认是图片在左文字在右,而大多数情况这样默认的的显示形式都不能满足我们的需求,接下来我就这个问题分享一下我的心得. 默认情况下,不设置的效果,都是居中实现 UIButton *bu ...
- spring 配置文件 数据库引入
一.mysql数据库引入 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSourc ...
- 学习npm和gulp的一些资料,先记着明天接着学习
Unix命令行程序和内建指令(百度百科) 将less编译成css的gulp插件 淘宝cnpm镜像 gulp教程之gulp-less gulp入门指南 查找npm的package.json的name配置 ...
- DEDE栏目内容调用
{dede:sql sql='Select content from dede_arctype where id=1'} [field:content/] {/dede:sql},
- 《python基础教程》笔记之 更加抽象
方法.函数和特性 函数和方法的区别在于self参数,方法(绑定方法)将它们的第一个参数帮顶到所属的实例上,因此这个参数可以不必提供.可以将特性绑定到一个普通函数上,这样就不会有特殊的self参数了,换 ...
- Spark学习笔记-三种属性配置详细说明【转】
相关资料:Spark属性配置 http://www.cnblogs.com/chengxin1982/p/4023111.html 本文出处:转载自过往记忆(http://www.iteblog.c ...
- 一个oracle存储过程
打开plsql,在packages文件夹里新建存储过程 在sql窗口中运行如下语句 create or replace package SY_USER_PKG1 is TYPE MYCURSOR IS ...
- Gson 禁止特殊字符转码
Map<String,String> map = new HashMap<String,String>(); map.put("url", "&a ...