定义常量对象,被const修饰的对象不能被更改

const int i = 42;			//正确,编译时初始化
const int j = get_size();	//正确,编译时初始化
const int l;				//错误,l未经初始化

默认状态下,const对象仅在文件内有效,要想在多个文件直接共享const对象,必须在变量的定义之前添加extern关键字

可以把引用绑定到const对象上,我们称之为对常量的引用。对常量的引用不能修改所绑定的对象

const int ci = 1024;	
const int &r1 = ci;		//正确,引用及其引用的对象都是常量
r1 = 2048;				//错误,r1是对常量的引用,不能修改
int &r2 = ci;			//错误,r2是非常量引用,不能指向一个常量对象

对const的引用可能引用一个并非const的对象

int i = 42;			
int &r1 = i;		//引用r1绑定1
const int &r2 = i;	//r2也绑定对象i,但是不允许通过r2改变i的值
r1 = 0;				//正确
r2 = 0;				//错误

和引用一样,可以将指针指向常量或者非常量。同时指针也是对象,因此指针也可以被const修饰。常量指针必须初始化,并且之后它的值就不能再更改了,把*放在const之前表示指针是一个常量

const double pi = 3.14;			//pi是一个常量
double *ptr = pi;				//错误,普通指针不能指向常量
const double *cptr = π		//正确,cptr可以指向一个double的常量
*cptr = 42;						//错误,不能给*cptr赋值
int errNumb = 0;
int *const curErr = &errNumb;		//curErr将一直指向errNumb
const double pi = 3.14159;
const double *const pip = π		//pip是一个指向常量对象的常量指针

我们用顶层cost表示任意的对象是常量,底层const则表示指针和引用复合类型的基本类型部分有关

int i = 0;
int *const p1 = &i;			//不能改变p1的值,顶层const
const int ci = 42;			//不能改变ci的值,顶层const
const int *p2 = &ci;		//可以改变p2的值,底层const
const int *const p3 = p2;	//即是顶层const又是底层const
const int &r = ci;			//对于引用的声明都是底层const

constexpr关键字

constexpr是C++11新引入的关键字,用来表示常量表达式。常量表达式是指值不会改变,并且在编译过程中就能得到计算结果的表达式。constexpr限定在了编译期就要初始化,const是可以再运行时初始化的。

int foo()
    return 5;
int main()
    const int p1 = foo();		//正确	
    constexpr int p2 = foo();	//错误,表达式必须含有常量值,无法调用非 constexpr 函数

constexpr只能定义字面值类型,如算术类型,指针和引用。而类似IO库,string类型则不属于字面值类型,也就不能被定义为constexpr。

尽管指针和引用可以被定义为constexpr,但是他们的初始值必须为nullptr或者0,或者是存储于某个固定地址中的对象。

auto和decltype关键字

auto和decltype关键字都可以进行类型推导,可以在编译期就推导出变量或者表达式所属的类型。

auto类型说明符:让编译器在编译期通过初始值推算变量的类型。在一条语句声明多个变量时,基础数据类型必须一样

auto i = 0, *p = &i;		//正确,i为整型,p为整型指针
auto sz = 0, pi = 3.14;		//错误,sz为整型,pi为双精度浮点数

在不声明的情况下,编译器会以引用对象的类型作为auto的类型。

auto也会忽略顶层const,保留底层const

int i = 0, &r = i;
auto a = r;		//a是int
const int ci = i, &cr = ci;
auto b = ci;	//b是int
auto c = cr;	//c是int
auto d = &i;	//d是int*
auto e = &ci;	//e是一个const int*

decltype类型说明符:用于编译器推导表达式类型,表达式并不会进行实际上的运算

decltype(exp) i;	
//exp可以是表达式,也可以是函数调用,这时候i是表达式的类型或者函数调用的返回值
//其他情况,若exp为左值,decltype(exp)是exp类型的左值引用

与auto不同,对于顶层const的处理不相同

const int ci = 0, &cj = ci;
auto x = ci;			//x是int
decltype(ci) y = ci;	//y是const int
auto z = cj;			//z是int
auto az = &cj;			//az是const int*
decltype(cj) cz = cj;	//cz是const int&

当exp是加了括号的变量,结果将是引用

int i = 42;
decltype((i)) d;	//错误,d是int&,必须初始化
decltype(i)	e;		//正确,e是未初始化的int
                            
Component java 抽象类 java抽象类怎么调用

JAVA抽象类及接口使用方法解析抽象类可以有自己的成员变量,继承抽象类的对象共用成员变量,也可以修改成员变量的值。可以有非抽象的方法。接口只能有static final的成员变量(一般不使用),只能有抽象的方法。public abstract class Door { String color; abstract void open(); abstract void close(); void k

File–>new–>Module没有Java怎么回事 fileinputstream文件不存在

FileInputStream主要用来创建输出文件流以写入具有指定名称的文件。根目录存在的情况下,如果文件不存在,则会生成新的文件,如果文件已经存在,则会去覆盖;但如果根目录不存在,它并不会自动的创建,此时,会抛出java.io.FileNotFoundException(系统找不到指定的路径。)此时,就需要我们先去创建该目录,再去写入数据。int len = 0; byte[] data

pythondataframe新命名 dataframe重命名列名

有时候经过某些操作后生成的DataFrame的列名称是默认的,为了列名标记已与理解,有时候我们会有修改列名称的需求。提供修改列名的方法如下: 假如有初始的DataFrame如下>>>import pandas as pd >>>a = pd.DataFrame({'A':[1,2,3], 'B':[4,5,6], 'C':[7,8,9]}) 4.报错2_Seata启动报错:Initialization of output ‘file=xxxlogs/seata_gc.log‘ using options ‘(null)‘ failed. 5.C++中一些小细节