C++变量和基本类型知识概要总结

烂漫一生 提交于 2020-02-26 15:38:40

整合基本的关于c++的变量和基本类型的知识。参考于C++primer第二章
仅包含部分,而非全部


inti=b;       //i的值为1
i= 3.14;         //i的值为3
double pi = i;         // pi的值为3.0
unsigned char C = - 1;       //假设char占8比特,c的值为255
signed char c2 = 256;         //假设char占8比特,c2的值是未定义的

注意:当我们赋给无符号类型一个超过它表示范围的值时,结果就是初始值对无符号类型所表示的数值总值取模后的余数。

举个清新易懂的例子
例如:八比特大小的unsigned char 可以表示0至255区间内的值,如果赋了一个区间以外的值,则实际值就是该值对256取模后所得的余数。-1赋值给unsigned char的结果时255.
但是!!赋值给有符号类型超过它表示范围的值时,结果就是未定义的。程序可能继续工作,可能崩溃,也可能产生垃圾数据。

int类型的加了一个无符号值时,int会先变成无符号类型然后再操作。
若两个无符号相减后变成负数了,结果会是取模后的值

‘A’ 和 "A"是有区别的,'A’就是一个单独的字符A,而"A"则代表了一个字符的数组,包含两个字符,一个是字母A ,另一个是空字符。

对于C++程序员来说,变量和对象一般可以互换使用

初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含
义是把对象的当前值擦除,而以一个新值来替代。
初始化的几个语句:

int a = 0;
int a = {0};
int a {0};

用花括号初始化,叫列表初始化,注意:当用于内置类型的变量时,这样初始化就会报错。
默认初始化


关于复合类型变量:引用和指针

引用:说白了就是给一个已经存在的对象所起的另外一个名字而已。
注意:引用时必须初始化
指针:把int变量 直接赋值给指针是错误的操作。即使int变量的值刚好等于0也是不行滴;

任何非0指针对应的条件值都是true

关于指向指针的引用:
int o;
int *j ;
int *&p = j; // 从右向左读,先是&所有是一个引用,然后是*所以是引用的类型是一个指针。
p = &o;
*p = 0;
关于const

注意点:

  • 1、只能初始化,代码中不能被修改值,否则会报错。
  • 2、必须要初始化,只定义而不初始化会报错。

除了以上两点,别的跟正常变量一毛一样,

关于extern

作用:extern const int buf; 若一个程序中存在多个文件,又想让所有的文件都可以使用同一个常量(const),那就需要用到前面写的语句了。

关于对const对象的引用:

原则记住就是const对象不能被更改,所以,用int变量去引用常量时会出错,而用常量去引用int变量时不会出错。

注意点:初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。

什么意思呢,生动形象的例子来了:

double j = 2.5;
const int &o = j;

这样是阔以的,很正确。

double j = 2.5;
int &o  = j;

这样就是错误的❌
也就是说不是常量类型的引用是不可以被初始化成类型不同的值的。

原因呢:
就在于const int &o = j;这个过程中,编译器的处理是特殊的。
会先创一个临时变量temp
const int temp = j;
const int &ri = temp;
这样下来每一步都非常之正确了。

那为什么对于int &o = j;不再创建一个临时变量呢???
因为这时很多余的操作,C++就干脆把这个定义为非法的。

到这里看着很蒙,于是决定归纳总结一下:

  • 只有常量和不是常量的区别时
  • 1.尝试先定义非常量
    ①引用:
    success
    ②指针:
    success
  • 2.尝试先定义常量
    ①引用:
    error
    ②指针:
    error
  • 既有常量区别,也有数据类型的区别时
  • 1.尝试先定义非常量
    ①引用:
    success
    ②指针:
    error
  • 2.尝试先定义常量
    ①引用:
    error
    ②指针:
    error

弄了半天,其实就两句话。。

  • 只要是用变量指向或是引用常量时,都会出错。即先定义了常量的情况;
  • 只要使用常量指向或是引用变量时,除了用常量指向不同数据类型的变量时才会出错,别的时候都是通过的。

const int *j ; 不报错
const int p; 报错

所以指向常量的指针当然不需要初始化了。
还有,注意注意注意 常量引用可以直接等于一个值。
比如, cosnt int &p = 5.3;

指向常量的指针
const int *P;

常量指针
int a = 5;
int *const p = &a;
指向常量的常量指针const int *const p = &a;

只要从右往左读就很easy啦

如果是一个指向普通变量的常量指针,那么可以通过*指针来改变所指对象的值,只是这个指针将只能指向这一个变量,不能再指向别的了。
要是是一个指向常量的常量指针,那就什么都动不了了

*注意注意:const int p;这个是合法的,因为这实际上是一个指针,只不过是指向常量的指针而已,所以不需要初始化。


关于const的更多

这个定义很简单,顶层const表示指针本身是一个常量,而底层const表示所指对象是一个常量。

据我观察,定义这个名词的目的就是想帮助分别出错的情况。就是我上面发现的有几种特别的情况然后总结出来的两句话:

只要是用变量指向或是引用常量时,都会出错。即先定义了常量的情况;
只要使用常量指向或是引用变量时,除了用常量指向不同数据类型的变量时才会出错,别的时候都是通过的。

关于常量表达式:

值不会改变并且再编译过程就能得到计算结果的表达式就是常量表达式了。
通过句子理解确确实实没有通过来的例子实在。。

const int max = 20;  //max是常量表达式
const int limit = max+1;  //limit是常量表达式
const int sz =  get_size();  //sz不是,因为get_size()这个函数需要运行才能得到值,而不能编译过程就得到结果。
constexpr变量

用处:只要是constexpr类型的就可以用编译器来验证变量的值是否是一个常量表达式。
constexpr int sz = size(); //只有当size是一个constexpr函数时才是一条正确的声明语句。

constexpr和指针的纠纷

一个constexpr指针的初始值必须是nullptr或者0,或者是存储与某个固定地址的对象。

const int *p = nullptr;   //p是一个指向整型常量的指针。
constexpr int *p = bullpr;   //p是一个指向整数的常量指针。

请仔细观察上面的两个式子!!(为什么要这么定义用法。。/(ㄒoㄒ)/~~)
与其他常量指针类似,constexpr指针既可以指向常量也可以指向一个非常量。

一个constexpr指针的初始值必须是nullptr或者0,或者是存储与某个固定地址中的对象

const int *p = nullptr;
constexpr int *q = nullptr;

注意看p和q的区别,p是一个指向常量的指针,而q就是一个常量指针,指向一个整型。


关于类型别名

注意using 和 typedef的用法区别

using wages = double;
typedef double wages;

关于小细节方面的有一点需要注意,看下面的例子:

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

注意注意cstr是一个指向char常量的指针,而不能把pstring分开看。

关于auto

一般会忽略掉顶层const,同时底层const则会保留下来。
譬如

const int b;
auto c = b; 此时c的类型为整型
关于decltype

这里突然提到引用,引用从来都是作为其所指的对象的同义词出现,只有在decltype处是个例外。

怎么体现呢?

int a, &b=a;
decltype (b) z;//此处就体现了引用,即z也是个引用,必须有初始化否则语法错误。

decltype里发现有好多奇葩设定😓

记住例子吧

int a = 42, *p = &a, &r = a;
decltype(r+0) b;//正确,虽然r是引用,但是引用放在表达式中,表达式的结果并不是引用
decltype(*p) c;//错误,指针的解引用的整数类型
decltype((a)) e;//错误, 在decltype中加多加一层括号的结果就永远是引用。引用必须初始	化。

如果i是int,则表达式i=x的类型是int&。
s
o
decltype(a=b) d=a; //–就很容易理解

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!