首页 > 其他分享 >const 和 constexpr

const 和 constexpr

时间:2024-04-28 23:45:34浏览次数:16  
标签:const 常量 修改 int constexpr 对象

修饰符const

   const 关键字 让被修饰的对象为只读,不可以修改其值。

应用场景

   const的应用场景主要有三种,第一种是修饰普通变量,第二种是修饰指针或引用,第三种是修饰成员函数。

常变量

   可以读取变量,不可进行写入操作。


//可以直接用常量初始化
const int a = 6;  
a = 9;    //错误, a 是可读类型

//可以用变量初始化
int b = 3;
const int c = b;

  像这种情况,const 修饰的变量只能定义时初始化进行赋值,且必须初始化。

const int d; //错误,未进行初始化
const int d = 5; //正确,进行了初始化

指针和引用

  先来介绍两个概念:

  1. 顶层const: 不可修改对象的值
  2. 底层const: 不可修改指向对象的值
int a = 5;  
int b = 6;  

const int *p = &a; //这个是底层const,无法修改指向对象的值  
*p = 15;   //错误,无法修改指向对象的值  
 a = 15;    /* 这是正确的,const 只是无法通过 p 对象 来修改指向 a 对象的值,  
            但通过 a 对象本身可以进行修改 */
 p = &b;    //这个是允许的,可以修改 p 所指向的对象  

int *const q = &a; //顶层const,无法修改对象的值  
q = &b;    //不可以修改 q 对象的值  
*q = 20;   //这个是可以的,其指向的对象没有限制  

  对于引用来说,它本身不是对象,只是对象的别名,像标签一样,与其指向的对象绑定在一起,但 const 修饰之后 又有一些特例:

/* 可以绑定非常量对象 */
int d = 2;
const int &p = d;

/* 可以绑定常量 */
int &a = 0;   //错误
const &a = 0;  //正确

/* 可以绑定常量表达式 */
int b = 1;
int &c = 2*b;   //错误
const int &c = 2*b;   //正确

/* 其实对于对于常量引用来说,只要等号右边可以转化为引用所指定的类型,都可以进行初始化 */

成员函数

  对成员函数用 const 修饰,意味着在这个函数内对 类的任何成员不能进行修改。

#include <iostream>

class Entity {
private:
    int a;
    int b;

public:

    int get() const {
        //a++; // 这是错误的,const 修饰意味着不能对类成员进行修改
        return a;
    }
    
};

void put(const Entity &x) {
	std::cout << x.get() << std::endl;
}

int main() {
	Entity e;
	put(e);
}

  上面的程序显然是对的,那么对其进行小的修改:

#include <iostream>

class Entity {
private:
    int a;
    int b;

public:

    int get(){  //删除了const    
	return a;
    }
    
};

void put(const Entity &x) {
	std::cout << x.get() << std::endl;  /*报错,因为参数类型 const 修饰
										而get()汉书可能修改 x,尽管它并未实现,
										但它存在实现的可能*/
}

int main() {
	Entity e;
	put(e);
}

  稍微总结一下就是,const 修饰的成员函数,保证了该函数无法对类的任何成员进行修改。这种修饰是绝对严格的,即使你并未对其进行修改,但存在可能性,就会报错,举一个例子:

#include <iostream>

void putnum(int &x) {    /*将其改变为putnum(const int &x) 或 putnum(int x) 或
                          putnum(const x) 便正确了,排除修改成员变量的可能*/

};
class Entity {
private:
    int a = 1;
    int b = 2;

public:

    int get() const{
        
        putnum(a);    /*这里报错了,因为putnum()函数存在修改成员变量a的可能,
                      即使什么都没做*/
        return a;
    }

};

void put(Entity& x) {
    std::cout << x.get() << std::endl;
}

int main() {
    Entity e;
    put(e);
}

默认状态下,const对象仅在文件内有效

  这是一个补充知识点:如果有多个文件的话,const 修饰的变量只能在被定义的编译单元中使用,没有可共享性,也就是内部链接。想要实现const 对象在不同编译单元间的共享,需要在定义和声明前都加上 extern 关键字,注意,是定义和声明都需要 extern 关键字。

/* 在main.cpp中 */
const int e = 7;   //错误,这种定义是不正确的

extern const int e = 7;    //正确
/* 在fuc.cpp中*/
extern const int e;


constexpr 和 常量表达式

  常量表达式:指的是值不变且在编译时就知道结果。

const int a = 1;         //是常量表达式
const int b = a + 1;     //是常量表达式
int c = 3;           //不是常量表达式,可修改其值
const int d = get(); //不是常量表达式,在运行时才知道结果    

constexpr 变量

  变量,可用constexpr修饰来让编译器检测变量值是否为常量表达式,声明为constexpr的变量一定是一个常量,且用常量表达式初始化。

constexpr int a = 1;
constexpr int b = a + 1;
constexpr int c = fuc(); //只有当fuc()是constexpr函数时,才是正确声明

constexpr指针

  constexpr指针只是对指针本身进行限制,对指向对象不起作用。

int a =5;
constexpr int *p = &a;   //指针是常量,不可修改
const int *q = &a;       //指针指向对象是常量,不可修改

标签:const,常量,修改,int,constexpr,对象
From: https://www.cnblogs.com/import-this05/p/18164768

相关文章

  • const在类和函数之间的运用
    const在类和函数之间的运用第一种情况简单来说就是如果声明了一个const类但是调用了非const的方法.那么编译会不通过->const类只能调用const方法,非const类就都可以调用示例代码:宏定义:#pragma#ifndef__CONST_OBJECT__#define__CONST_OBJECT__​#include<iostream>#incl......
  • C++,四种强制类型转换,static_cast,const_cast,dynamic_cast,reinterpret_cast
      #include<iostream>usingnamespacestd;structA{virtualvoidfunc(){cout<<"Afunc"<<endl;}};structB:publicA{voidfunc(){cout<<"Bfunc"<<endl;}};intmain(){c......
  • M. Triangle Construction
    原题链接题解如果存在某一条边的\(a_i>=2*(sum-a_i)\)那么这条边一定有点剩余无法连接,为什么?这条边上每取两个点作为底边点,就一定能去外面一个点作为顶点,且无交叉(顺时针或逆时针)code#include<bits/stdc++.h>#definelllonglongusingnamespacestd;intmain(){ll......
  • 52 Things: Number 20: How are Merkle-Damgaard style hash functions constructed?
    52Things:Number20:HowareMerkle-Damgaardstylehashfunctionsconstructed?52件事:第20件:Merkle-Damgaard风格的散列函数是如何构建的? Thisisthelatestinaseriesofblogpoststoaddressthelistof '52ThingsEveryPhDStudentShouldKnow' todoCr......
  • const 使用总结
    const关键字是用于定义一个不该被改变的对象,它的作用是告诉编译器和其他程序员不允许修改这个对象的值或者状态。当程序员看到使用const修饰的代码时就知道不应该修改对应对象的值,而编译器则会强制实施这个约束,任何违反这个规定的代码会在编译期间报错。它可以用于任何函数或者类......
  • 变量、常量(constant)
    java是一个强类型语言,每个变量都必须声明其类型;变量要素包含:变量名、变量类型、作用域typevarname=[=value][{,varname[=value]}];变量命名规范:所有的变量,方法,类名(见名知意)类成员变量:首字母小写,驼峰原则,eg:lastName类名,方法名,局部变量:首字母小写,驼峰原则常量:大写字母和......
  • Verification -- Basic Concepts ~ 4. Constraint Random Verification
    ConstraintRandomVerificationConstraintRandomVerification(CRV)是一种用于生成具有特定约束的随机测试用例的技术,以确保生成的输入激励满足某些设计要求。在CRV中,定义了一组捕获设计要求的约束,例如数据范围、时序要求和接口协议。然后,测试平台生成一组满足这些约束条......
  • As a reader --> NetDiffusion: Network Data Augmentation Through Protocol-Constra
    ......
  • var , let , const 区别
    1.作用域let与const存在块级作用域,var不存在块级作用域for(vari=0;i<5;i++){setTimeout(()=>{console.log(i)})}//输出5,5,5,5,5for(leti=0;i<10;i++){setTimeout(()=>{console.log(i)})}//输出0,1,2,3,42.重复......
  • Const关键字介绍
    Const关键字用于**声明一个常量或限制变量的修改**,确保其值不被改变。具体来看:1.**定义常量**:使用const关键字可以将变量定义为常量,这意味着一旦赋值后,其值就不允许再被修改。2.**修饰类成员函数**:在C++中,const可以用于修饰类的成员函数,表明该函数不会修改类的任何成员变量......