1、用const修饰函数的参数

  1. 参数是值传递

    由于函数将自动产生临时变量复制该参数,该参数无需保护,没必要用const

  2. 参数是指针传递或者引用传递

    const修饰的指针或引用所指向的值不可变。如果该参数只是起“被读取”的作用,最好用const修饰保护。

对于复合数据类型,最好使用引用传递,因为值传递的过程中要进行临时对象的构造,复制,析构,这些都会造成时间和空间的浪费。

class list {
string name;
public:
void show(const list& l) {
cout << name;
}
}

2、用const修饰函数的返回值

如果函数的返回值用const修饰,接受这个返回值的变量也只能用const修饰。

const int sum(int a, int b) {return a+b;}

int s = sum(1,1); //error
const s = sum(1,1); //编译通过

3、const 成员函数

任何不会修改数据成员的函数都应该声明为const 类型。如果在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将指出错误,这无疑会提高程序的健壮性。

class list {
string name;
public:
void show(list& l) const {
cout << name;
}
}

4 、const对象

const修饰的对象只能访问const函数和const成员变量

class list {
string name;
public:
void show(list& l) const {
cout << name;
}
void show2(list& l) {
cout << name;
}
} const list l;
l.show2(); //error
l.show(); //编译通过

const 对象只在当前文件有效,例如a.cc中定义:const int MAX = 999;,这时在b.cc中声明:extern const int MAX;,编译链接后会显示undefined reference to 'MAX'。解决办法是定义前边也加上extern

5 、与constexpr区别

  1. 对于修饰Object来说

    • const并未区分出编译期常量(编译时就可以确定的常量表达式)和运行期常量
    • constexpr限定在编译期常量,也就是说,编译器看见constexpr就可以在编译期计算,所以应该尽量将一个变量声明为constexpre
  2. 对于修饰函数来说

    • constexpr修饰的函数,返回值不一定是编译期常量

      #include <iostream>
      #include <array>
      using namespace std; constexpr int foo(int i)
      {
      return i + 5;
      } int main()
      {
      int i = 10;
      std::array<int, foo(5)> arr; // OK foo(i); // Call is Ok // But...
      std::array<int, foo(i)> arr1; // Error }

所以,对于constexpr需要两方面看待。

constexpr修饰的函数,简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值。但是,传入的参数如果不能在编译时期计算出来,那么constexpr修饰的函数就和普通函数一样了。不过,我们不必因此而写两个版本,所以如果函数体适用于constexpr函数的条件,可以尽量加上constexpr

而检测constexpr函数是否产生编译时期值的方法很简单,就是利用std::array需要编译期常值才能编译通过的小技巧。这样的话,即可检测你所写的函数是否真的产生编译期常值了。

6、指向常量的指针(pointer to const)、常量指针指针(const pointer) 与 constexpr指针

  • 指向常量的指针,又叫底层指针

    • 作用:不能通过指针修改值,无论指向的值是否是const, 指针本身可以改变指向。

      int a =1;
      const int b = 1;
      const int* p;
      p = &a;
      *p = 2;//错误
      p = &b;
      *p = 2; //错误
  • 常量指针,又叫顶层指针

    • 作用:不能修改指针的指向,指针本身是常量,所以必须在声明时初始化。

      int a = 1;
      int b = 1;
      int* const p = &a;
      p = &b; //报错
  • constexpr指针

    • 作用和常量指针(顶层指针)一样

注意!类型别名与常量指针

typedef int* ip;
int a = 1;
const ip p; //不能理解成 const int *p! 他等价于 int* const p; 也就是顶层指针,顶层指针必须初始化,所以这句是会报错的
const ip p = &a; //正确

7、const引用

int const& a;const int& a; 作用一样,可以不加区分。

参考:https://www.zhihu.com/question/35614219/answer/63798713

https://www.jianshu.com/p/34a2a79ea947

《C++ primer》2.4节

const用法及与constexpr区别总结的更多相关文章

  1. 【转】话说C语言const用法

    原文:话说C语言const用法 const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,意即其所修饰的对象为常量(immutable). 我们来分情况看语法上它该如何被使用. 1.函数体内修 ...

  2. const 用法全面总结

    C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,本人根据各方面查到的资料进行总结如下,期望对朋友们有所帮助. Const 是C++中常用的类型修饰符,常类型是指使用类 ...

  3. const用法详解(转)

    http://www.cnblogs.com/StudyRush/archive/2010/10/06/1844690.html 面向对象是C++的重要特性. 但是c++在c的基础上新增加的几点优化也 ...

  4. const 在C++中的区别

    一.Const作用    如下表所示: No. 作用 说明 参考代码 1 可以定义const常量 const int Max = 100; 2 便于进行类型检查 const常量有数据类型,而宏常量没有 ...

  5. JavaScript中const、var和let区别浅析

    在JavaScript中有三种声明变量的方式:var.let.const.下文给大家介绍js中三种定义变量的方式const, var, let的区别. 1.const定义的变量不可以修改,而且必须初始 ...

  6. c++ const用法小结

    const用法 1,定义全局变量的内存分配问题 #define  Pi_1  3.14       //使用#define宏 const double Pi_2 = 3.14    //使用const ...

  7. 实例讲述PHP面向对象的特性;;;php中const与define的使用区别

    php中const与define的使用区别 1.const:类成员变量定义,一旦定义且不能改变其值. define:定义全局常量,在任何地方都可以访问.2.define:不能在类中定义,而const可 ...

  8. const用法

    一.const作用 二.const用法 1.修饰一般常量   修饰符const可以用在类型说明符前,也可以用在类型说明符后. 例如: ; ; 2.修饰常数组  修饰符const可以用在类型说明符前,也 ...

  9. 浅谈HTTP中GET、POST用法以及它们的区别

    浅谈HTTP中GET.POST用法以及它们的区别 HTTP定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符.我们可以这样认为: 一 ...

  10. static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符

    一.static 与单例模式 单例模式也就是简单的一种设计模式,它需要: 保证一个类只有一个实例,并提供一个全局访问点 禁止拷贝  C++ Code  1 2 3 4 5 6 7 8 9 10 11 ...

随机推荐

  1. Linux进程通信-POSIX IPC

    前言 Linux POSIX IPC的可移植性是不如System V IPC的,但是我们只用Linux,并且内核版本高于2.6.6的话就不存在该问题了.也因为POSIX IPC出现的比较晚,借鉴了sy ...

  2. Power BI 14 DAY

    快消行业销售情况分析 分析目的 帮助经销商优化进.销.存各环节业务流程行为,实现进销存一体化管理,加快资金运转速度,实现销售利润最大化的目的 重要指标 销售类指标 动销次数:在一段期间内产品的销售次数 ...

  3. CF1823D Unique Palindromes

    题目链接 题解 知识点:构造. 首先反证法容易证明一个结论:每次增加一个字符,本质不同的回文子串至多增加一个. 那么无解的条件就是,\(c_i - c_{i-1} > x_i -x_{i-1}\ ...

  4. 【Unity3D】动画混合

    1 简介 ​ 2D动画.人体模型及动画.人物跟随鼠标位置中介绍了 Aniamtion.Animator.人体模型.人体骨骼.人体动画等基础知识及人体动画的应用,本文将进一步介绍动画混合. ​ 实现动画 ...

  5. 基于keras的时域卷积网络(TCN)

    1 前言 时域卷积网络(Temporal Convolutional Network,TCN)属于卷积神经网络(CNN)家族,于2017年被提出,目前已在多项时间序列数据任务中击败循环神经网络(RNN ...

  6. aspell命令

    aspell命令 aspell命令是一个交互式拼写检查器,其会扫描指定的文件或任何标准输入的文件,检查拼写错误,并允许交互式地纠正单词. 语法 aspell [options] command 参数 ...

  7. Oracle11gr2新增APPEND_VALUES提示

    在11.2中,Oracle新增了APPEND_VALUES提示,使得INSERT INTO VALUES语句也可以使用直接路径插入. 例子很简单: SQL> SELECT * FROM V$VE ...

  8. 使用@ControllerAdvice统一处理自定义异常

    最近工作中涉及到捕捉AOP方法中抛出的异常. 想针对某一种异常做一个统一的处理器并封装好异常信息以JSON格式交给前端进行提示. 主要实现的话有以下几步: 1.编写自定义异常类 package com ...

  9. git bash 的一些使用

    一般使用git bash需要的命令 先打开git bash: git init 可以初始化一个本地的仓库 git status 查看仓库信息 mkdir test 创建一个test的文件夹 cd te ...

  10. Aop @AfterReturning因返回类型不一致导致无法执行切面代码

    要做返回异常之后,所有操作回滚的操作,本来想着泛型用 Object 就表示所有返回类型是 CommonResult 并且加指定注解的都走这个通知的代码,但是如下配置,无论如何也不生效 进入源码里发现, ...