【C++系列一】

const限定符

const是用来定义不能被改变的变量。\(\color{red}因为const对象一旦创建后其值就不能再改变,所以const对象必须初始化。\)
还有一种是利用一个对象去初始化另外一个const对象,那么这个对象是不是const对象都无所谓。

const的限定范围

一般而言,const关键字定义的变量是在文件内部有效。为了在多个文件中可见,那么就需要在多个文件中各自定义同名变量。但是这种做法比较蠢。
那么有时需要const变量在多个文件共享,这个时候可以对const变量的声明和定义都加上extern关键字,这样只需要定义一次即可。

const的引用

说白了就是对常量的引用,但是对常量的引用不能用作修改它所绑定的对象:

const int ci = 1024;
const int& r1 = ci;
r1 = 42;    //不能修改;
int &r2 = ci;   //也不能这样使用,因为会试得非常量引用指向常量对象,且存在修改风险;

初始化和const的引用

之前说,引用类型必须和所引用对象类型一致,但是这里存在两个例外:
1)在初始化常量引用时允许用任意表达式作为初始值,只要表达式结果能转换成就行;甚至允许一个常量引用绑定非常量对象、字面值和表达式;

int i = 42;
const int& r1 = i;  //OK!

本质上是绑定到一个临时量,而非本体;等价于下面:

int i = 42;
const int temp =  i;
const int& r1 = temp;

2)对const引用可能引用的并非一个const对象
常量引用只是对引用可参与的操作做出了限制,但是对引用对象本身是不是一个常量未做限定:

int i = 42;
int& r1 = i;
const int& r2 = i; //只是说明不能通过r2去修改i的值;
r1 = 22;    //但可以通过其他方式去修改;

指针和const

这个就是一直比较常见的const指针和指针常量的范围;
指针常量:就是指针指向一个常量,这个指针不能用来改变其所指向的对象的值;
常量指针:说的是这个指针是固定死了,但是指向的对象却是可以更改的;

const double pi = 3.14;
const double* ptr1 = π   //指针常量;
int errNumb = 0;
int* const ptr2 = &errNumb;     //常量指针;
*ptr2 = 1;  //OK

顶层const

const本身是不是常量以及指针指向的对象是不是常量,可以将两个名词进行区分:
顶层const:表示指针本身是个常量;
底层const:表示指针所指向的对象是个常量;
更一般的说,顶层const可以表示任意对象是常量;底层const则是与指针和引用等复合类型的基本类型部分有关;指针是个比较特殊的类型,既可以是顶层也可以是底层const。
顶层const和底层const使用主要是在拷贝时候差异明显:
1)顶层const拷贝不受影响;
2)底层const,拷入和拷出对象必须具有相同底层const资格,或者两个对象的数据类型必须能够转换,一般来说是非常量可转常量,反之则不行;

const int ci =42;
const int *p2 = &ci;
const int* const p3 = p2;

int *p = p3;    //error
p2 = p3;    //OK
p2 = &ci;

constexpr和常量表达式

常量表达式:指值不会改变且在编译期间就已经确认计算结构的表达式;
因为在实际使用过程中,很难分辨一个初始值是不是常量表达式,为了解决这个问题,C++11就推出新关键字constexpr来帮助验证一个变量的值是否为常量表达式,声明为constexpr的变量一定是一个变量,而且必须用常量表达式初始化。

constexpr int mf = 20;
constexpr int limit = mf + 1;

constexpr指针

用constexpr声明中定义一个指针,那么限定符constexpr是对指针有效的,与指针的对象无关:

const int*  p = nullptr;    //底层const
constexpr int* q = nullptr; //顶层const;

类型别名

C中我们习惯用typedef来命名类型别名;
在C++11中,则使用using关键字来命名别名;

using ll = long long;

需要注意复合类型导致的问题:

typedef char* pstring;
const pstring cstr = 0;
const pstring *ps;

这里值得注意的是 cstr其实是一个指向char的常量指针,而非是指向常量字符的指针;
嘿嘿,如果你把pstring用char*带入其中,那么就会得到cstr是指向常量字符的指针,那么就得到截然不同的意思。

auto类型说明符

有的时候是难以清楚地知道表达式的类型,有的时候类型名又臭又长,C++11使用auto关键字来让编译器帮我们去推导类型;
需要值得注意的是用auto推导一行变量时,必须类型一致:

auto sz = 0, pi = 3.14; //error

auto一般会忽略顶层const,同时底层const则会保留下来:

const int ci = i, &cr = ci;
auto b = ci;    //int
auto c = cr;    //int
auto d = &i;    //int*
auto e = &ci;   //const int*;

如果希望保留顶层const,那么需要明确指出;

const auto f = ci;

对于引用也是一样的:

auto& g = ci;
auto& h = 42;   //error,不能为非常量引用绑定字面值;
const auto& j = 42; //ok

decltype类型指示符

decltype只是计算数据类型,而不做实际计算;
decltype处理顶层const和引用方式与auto有些不一样:
1)如果decltype使用的变量表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内);
2)一般而言,引用都是作为所指对象的同义词出现,只有在decltype时则是一个例外;

如果decltype中的是表达式,则返回根据计算结果对象类型;
在这里需要提醒的是:
对于decltype所用表达式而言,变量名不加上一对括号,则得到的结果就是该变量的类型,如果加上括号(一层或多层),编译器就会将其当成一个表达式,变量可以当做是赋值语句左值的特殊表达式,所以这样decltype就会将其当成一个引用:

decltype((i)) d ; //error, d是int&,需要初始化;
decltype(i) e;  //ok, e是int;

原文链接: https://www.cnblogs.com/zhanghanLeo/p/13090594.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    【C++系列一】

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/354358

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午8:32
下一篇 2023年3月2日 上午8:33

相关推荐