1.const char *p,char const *p,char * const p

对于C++而言,没有const * 修饰符,所以,const只可以修饰类型或者变量名。因而const char *p,char const *p是等价的。

const char *p = "abc";

意义为:不可以改变p所指向的内容,即*p不可以改变,*p = "bcd";是错误的。

char a,b;

char * const p = &a;

意义为:不可以改变p的指向,即p的内容不可以改变,p = &b;是错误的。

2.函数指针

 typedef 行为有点像 #define 宏,用其实际类型替代同义字。

 不同点:typedef 在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换

用法一:

typedef int (*MYFUN)(int, int)
这种用法一般用在给函数定义别名的时候
上面的例子定义MYFUN 是一个函数指针, 函数类型是带两个int 参数, 返回一个int 

分析这种形式的定义的时候可以用下面的方法: 
先去掉typedef 和别名剩下的就是原变量的类型. 
去掉typedef和MYFUN以后就剩: 
int (*)(int, int)

用法二:

typedef给变量类型定义一个别名.

typedef struct{ 
int a; 
int b; 
}MY_TYPE

这里把一个未命名结构直接取了一个叫MY_TYPE的别名, 这样如果你想定义结构的实例的时候就可以这样: 
MY_TYPE tmp;

第二种用法:typedef 原变量类型 别名

简单的函数指针的用法

//形式1:返回类型(*函数名)(参数表)

char(*pFun)(int);

//typedef char(*pFun)(int)   //跟上一行功能等同

/*typedef的功能是定义新的类型。第一句就是定义了一种PTRFUN的类型,并定义这种类型为指向某种函数的指针,这种函数以一个int为参数并返回char类型。*/

char glFun(int a){return;}

void main()

{

pFun =glFun;

(*pFun)(2);

}

第一行定义了一个指针变量pFun.它是一个指向某种函数的指针,这种函数参数是一个int类型,返回值是char类型。只有第一句我们还无法使用这个指针,因为我们还未对它进行赋值

第二行定义了一个函数glFun().该函数正好是一个以int为参数返回char的函数。我们要从指针的层次上理解函数-函数的函数名实际上就是一个指针函数名指向该函数的代码在内存中的首地址

  1. //#include<iostream.h>
  2. #include<stdio.h>
  3.  
  4. typedef int (*FP_CALC)(int, int);
  5. //注意这里不是函数声明而是函数定义,它是一个地址,你可以直接输出add看看
  6. int add(int a, int b)
  7. {
  8. return a + b;
  9. }
  10. int sub(int a, int b)
  11. {
  12. return a - b;
  13. }
  14. int mul(int a, int b)
  15. {
  16. return a * b;
  17. }
  18. int div(int a, int b)
  19. {
  20. return b? a/b : -1;
  21. }
  22. //定义一个函数,参数为op,返回一个指针。该指针类型为 拥有两个int参数、
  23. //返回类型为int 的函数指针。它的作用是根据操作符返回相应函数的地址
  24. FP_CALC calc_func(char op)
  25. {
  26. switch (op)
  27. {
  28. case '+': return add;//返回函数的地址
  29.   case '-': return sub;
  30. case '*': return mul;
  31. case '/': return div;
  32. default:
  33. return NULL;
  34. }
  35. return NULL;
  36. }
  37. //s_calc_func为函数,它的参数是 op,
  38. //返回值为一个拥有 两个int参数、返回类型为int 的函数指针
  39. int (*s_calc_func(char op)) (int, int)
  40. {
  41. return calc_func(op);
  42. }
  43. //最终用户直接调用的函数,该函数接收两个int整数,和一个算术运算符,返回两数的运算结果
  44. int calc(int a, int b, char op)
  45. {
  46. FP_CALC fp = calc_func(op); //根据预算符得到各种运算的函数的地址
  47. int (*s_fp)(int, int) = s_calc_func(op);//用于测试
  48. // ASSERT(fp == s_fp); // 可以断言这俩是相等的
  49. if (fp) return fp(a, b);//根据上一步得到的函数的地址调用相应函数,并返回结果
  50. else return -1;
  51. }
  52.  
  53. void main()
  54. {
  55. int a = 100, b = 20;
  56.  
  57. printf("calc(%d, %d, %c) = %d\n", a, b, '+', calc(a, b, '+'));
  58. printf("calc(%d, %d, %c) = %d\n", a, b, '-', calc(a, b, '-'));
  59. printf("calc(%d, %d, %c) = %d\n", a, b, '*', calc(a, b, '*'));
  60. printf("calc(%d, %d, %c) = %d\n", a, b, '/', calc(a, b, '/'));
  61. }

3.const用法

  const修饰指针就不用细说了,上面已经将难点说清楚了。这里主要述说const用于引用和类成员函数。

  函数传值:常引用的好处一个是减少值传递时的对象拷贝时间,二是防止原值被更改。这里的好处不细说了。

  函数返回值:(一般用于类的成员变量,且该变量不能被外界改变,自身所占空间很大)使用常引用就非常适合,既可以减少函数返回时对变量的拷贝时间,又可以在使用该函数的时候减少拷贝时间,防止更改。但前提是接收该函数返回值的对象也要是常引用,否则,如果为引用,则编译器会报错,因为左值不可改变;如果为变量,还是对返回值进行了拷贝,没有达到减少时间的目的。

  const修饰成员函数

  (1)const修饰的成员函数不能修改任何的成员变量(mutable修饰的变量除外。在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中)

  (2)const成员函数不能调用非const成员函数,因为非const成员函数可以会修改成员变量

  1. const QList<message> & GetCoordinate() const
  2. {
  3. return m_Message;
  4. }
  5. const QList<DataBase::message> &data = m_DataBase->GetCoordinate();//去掉const编译器会报错
  1. #include <iostream>
  2. using namespace std;
  3. int _tmain(int argc, _TCHAR* argv[])
  4. {
  5. int a = 5;
  6. const int &b = a;
  7. const int &c = b;
  8. int n = b;
  9. int m = b;
  10. cout << &n << ends << &m << ends << &b << ends << &c << ends << &a;
  11. return 0;
  12. }
  13. //运行结果:
  14. /*002EFA28 002EFA1C 002EFA4C 002EFA4C 002EFA4C

  const的一些建议

  • 要大胆的使用const,这将给你带来无尽的益处,const节约内存空间,但前提是你必须搞清楚原委;
  • 在参数中使用const应该使用引用或指针,而不是一般的对象实例;
  • const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;
  • 任何不会修改数据成员的函数都应该声明为const 类型。

参考资料:http://blog.chinaunix.net/uid-24227137-id-2954442.html

C++之常指针,指针常量,函数指针,const用法总结的更多相关文章

  1. C++中的指针、数组指针与指针数组、函数指针与指针函数

    C++中的指针.数组指针与指针数组.函数指针与指针函数 本文从刚開始学习的人的角度,深入浅出地具体解释什么是指针.怎样使用指针.怎样定义指针.怎样定义数组指针和函数指针.并给出相应的实例演示.接着,差 ...

  2. [Reprint]C++普通函数指针与成员函数指针实例解析

    这篇文章主要介绍了C++普通函数指针与成员函数指针,很重要的知识点,需要的朋友可以参考下   C++的函数指针(function pointer)是通过指向函数的指针间接调用函数.相信很多人对指向一般 ...

  3. C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)

    //多态的原理--虚函数指针--子类虚函数指针初始化 #include<iostream> using namespace std; /* 多态的实现原理(有自己猜想部分) 基础知识: 类 ...

  4. C++(二十二) — 指针变量、函数指针、void指针

    1.指针变量 (1)指针变量必须在初始化后才可以正常使用,初始化就是给他分配一个有效的数据地址. 先初始化,后使用. (2)指针可以进行加减运算,++ 或者 --:将指针的位置向前或者向后移动一个数据 ...

  5. C++学习之普通函数指针与成员函数指针

    函数指针(function pointer)是通过指向函数的指针间接调用函数.相信很多人对指向一般函数的函数指针使用的比较多,而对指向类成员函数的函数指针则比较陌生.我最近也被问到了这方面的问题,心中 ...

  6. 函数指针和成员函数指针有什么不同,反汇编带看清成员函数指针的本尊(gcc@x64平台)

    函数指针是什么,可能会答指向函数的指针. 成员函数指针是什么,答指向成员函数的指针. 成员函数指针和函数指针有什么不同? 虚函数指针和非虚成员函数指针有什么不同? 你真正了解成员函数指针了吗? 本篇带 ...

  7. C 指针常量 和常量指针 指向常量的指针常量的使用

    #include <stdio.h> /* 指针常量 和常量指针 指向常量的指针常量 */ int main() { int a = 100; int b =200; int* const ...

  8. (60) 结构体指针、结构体变量嵌套、结构体指针嵌套、函数指针、数组指针、指针数组、typedef 综合运用

    #include<stdio.h> #include<iostream> #include<malloc.h> /* author : 吴永聪 program: 结 ...

  9. 指针常量&常量指针&指向常量的指针常量

    搞不懂不吃晚饭 (1)指针常量 指针常量是一个常量,但是是指针修饰的. 格式:int * const p; 例如 int a, b; int * const p = &a;//指针常量 //分 ...

  10. 使用std::function 把类成员函数指针转换为普通函数指针

    前言 这是改造前一篇 设计模式 的基础,使通知者不必知道观察者的类名和函数名,只需要知道更新函数的原型即可. 开发环境:WIN7 32位 + VS2010 发现在VS2005中使用std::funti ...

随机推荐

  1. 第二十五篇 -- C++宝典中的图书管理系统

    此篇文章是基于C++宝典写的图书管理系统,本人对其中的部分做了相应修改,并且以现有格式替代原有格式,使程序更加清晰明了.此程序运行在VS2017上. 系统设计 图书管理系统分为四个模块:图书管理模块. ...

  2. 渗透测试思路 - CTF(番外篇)

    渗透测试思路 ​ Another:影子 (主要记录一下平时渗透的一些小流程和一些小经验) CTF(番外篇) ​ 笔者是一个WEB狗,更多的是做一些WEB类型题目,只能怪笔者太菜,哭~~ 前言 ​ 本篇 ...

  3. 深入刨析tomcat 之---第21篇 tomcat 对jsp页面支持的实现原理

    writedby 张艳涛 web技术,以前的动态网页技术多是jsp页面,比如点击一个菜单目录,直接访问了一个LRJSDetailInput.jsp页面,这个页面 有<html><bo ...

  4. 🔥 LeetCode 热题 HOT 100(81-90)

    337. 打家劫舍 III 思路:后序遍历 + 动态规划 推荐题解:树形 dp 入门问题(理解「无后效性」和「后序遍历」) /** * Definition for a binary tree nod ...

  5. 如何从二维平面n个点中寻找距离最近两个点?

    如何理解分治算法 什么是分治算法?简单来说就是"分而治之",也就是将原问题划分成n个规模较小的,并且结构与原问题相似的子问题,然后去递归地解决这些子问题,最后再合并其结果,就得到原 ...

  6. CVE-2021-3156 复现

    测试环境 OS: Ubuntu 18.04.5 LTS GCC: gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) Make: GNU Make 4.1 ...

  7. 清晰易懂的RxJava入门实践

    导入 我相信大家肯定对ReactiveX 和 RxJava 都不陌生,因为现在只要是和技术相关的网站,博客都会随处见到介绍ReactiveX和RxJava的文章. ReactiveX Reactive ...

  8. Linux线程简单介绍

    1.进程与线程 2.使用线程的理由 3.有关线程操作的函数 4.线程之间的互斥 5.线程之间的同步 6.试题最终代码 1.进程与线程 进程是程序执行时的一个实例,即它是程序已经执行到何种程度的数据结构 ...

  9. IllegalArgumentException occurred while calling setter for property

    参考https://blog.csdn.net/qq_41192690/article/details/80659427 主码 是 integer类型的 就不要在写成这个样子了 把type=" ...

  10. 零基础学Java之Java学习笔记(一):Java概述

    什么是Java? Java是一门面向对象编程语言,可以编写桌面应用程序.Web应用程序.分布式系统和嵌入式系统应用程序. Java特点有哪些? 1.Java语言吸收了C++语言的各种优点,具有功能强大 ...