c/c++ 复习基础要点01-const指针、指针函数 函数指针、new/delete与malloc/free区别与联系

时间:2023-01-29 21:30:57

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区别与联系的更多相关文章

  1. c&plus;&plus;复习基础要点02 虚函数与模板 与static inline是否共存

    1.      虚函数能否定义为模板函数 当一个类有虚函数时,它一定有一个虚表,用来纪录每个虚函数的实际地址.这也就是说这个虚表的大小是在编译期就确定了的.有多少个虚函数,虚表就纪录几个.       ...

  2. c&bsol;c&plus;&plus;复习基础要点08--c&plus;&plus;单例模式

    单例模式有许多种实现方法,在c++中,甚至可以直接用一个全局变量做到这一点,但是这样的代码显得不优雅.使用全局对象能够保证方便地访问实例,但是不能保证只声明一个对象——也就是说除了一个全局实例外,仍然 ...

  3. c&bsol;c&plus;&plus;复习基础要点16----枚举类型

    枚举类型: 语法格式: enum 枚举类型名 {变量值列表}; 例如: enum  Weekday{sun, mon, tue, wed, thu, fri, set}; 声明了枚举类型后,就可以定义 ...

  4. 【C&plus;&plus;自我精讲】基础系列二 const

    [C++自我精讲]基础系列二 const 0 前言 分三部分:const用法.const和#define比较.const作用. 1 const用法 const常量:const可以用来定义常量,不可改变 ...

  5. 小猪猪C&plus;&plus;笔记基础篇(六)参数传递、函数重载、函数指针、调试帮助

    小猪猪C++笔记基础篇(六) ————参数传递.函数重载.函数指针.调试帮助 关键词:参数传递.函数重载.函数指针.调试帮助 因为一些事情以及自己的懒惰,大概有一个星期没有继续读书了,已经不行了,赶紧 ...

  6. &lbrack;C&plus;&plus; Primer Plus&rsqb; 第7章、函数(一)程序清单——递归,指针和const,指针数组和数组指针,函数和二维数组

    程序清单7.6 #include<iostream> using namespace std; ; int sum_arr(int arr[], int n);//函数声明 void ma ...

  7. const关键字与数组、指针

    目录 const关键字 const修饰数组 const修饰指针 用两个const修饰指针 @ 开始回顾C基础知识.C中使用指针是很危险的事情,一个不慎就会造成程序崩溃,因此对于传入函数的参数进行保护就 ...

  8. 034 01 Android 零基础入门 01 Java基础语法 04 Java流程控制之选择结构 01 流程控制概述

    034 01 Android 零基础入门 01 Java基础语法 04 Java流程控制之选择结构 01 流程控制概述 本文知识点:Java中的流程控制相关概念的认识 三大流程控制语句结构的简介 顺序 ...

  9. CORS基础要点:关于dataType、contentType、withCredentials

    事实上,面试时我喜欢问跨域,因为多数开发者都知道它并且常用,而我希望能从面试者的回答中知道他在这个问题的深入程度,进一步看看面试者研究问题的思维方式及钻研精神,然而确实难到了很多人,当然这也不是面试通 ...

随机推荐

  1. mac 笔记

    ---恢复内容开始--- /* 因为外出mac 办公的时候越来越多,有时候4g wifi 流量告急,不得不寻找破解之道. */ 安装port& aircreak-ng sudo port in ...

  2. codeforces 477A A&period; Dreamoon and Sums&lpar;数学&rpar;

    题目链接: A. Dreamoon and Sums time limit per test 1.5 seconds memory limit per test 256 megabytes input ...

  3. css中常用的标签

    最常用的标签 left 左 top 上 right 右 bottom 下 font 字体 size 大小 width 宽度 height 高度 class 类 label 标签 form 表单 gro ...

  4. Java-Poi 读取excel 数据

    一直想着使用java操作excel,但有时各种原因一直没有实现.由于工作无意间做了个其他demo,为了进一步发散就涉及到了使用excel,为此开始正式接触POI,虽然限制不是很了解POI,但是通过查阅 ...

  5. 058、flannel概述(2019-03-27 周三)

    参考https://www.cnblogs.com/CloudMan6/p/7412150.html   flannel 是 CentOS开发的容器网络解决方案.flannel 为每个host分配一个 ...

  6. zabbix-agent 在SElinux Enforcing 状态的文件权限问题及解决办法

    因为某种原因必须要开启SElinux,用yum装了一个zabbix-agent 替换了一下配置文件结果悲剧了 # systemctl restart zabbix-agent ● zabbix-age ...

  7. RN TextInput用法

    效果图: 代码: import React, {Component} from 'react' import {StyleSheet, View, Text, TouchableOpacity, Te ...

  8. WCF来传递DataTable的Bug

    Wcf,客户端与服务器之间在传递DataTable(由于数据库字段不确定暂时用DataTable而不是用实体对象传递)时,发现有的DataTable可以直接传递没有问题 解决方案: DataTable ...

  9. Python学习笔记 - MySql的使用

    一.安装MySql模块 Python2.X pip install MySQLdb Python3.X pip install pymysql 二.数据库连接接口 由于Python统一了数据库连接的接 ...

  10. java——时间复杂度、动态数组

    O(n)不一定小于O(n^2),要具体来看,而我们说的这种时间复杂度其实是渐进时间复杂度,描述的是n趋近于无穷的情况. 动态数组的时间复杂度: 添加操作:O(n) addLast()的均摊复杂度为O( ...