变量和基本类型---C++ 基础

前言

之前笔试了几家公司,居然在语言这种基础的问题上摔跟头。不得不进行恶补。科研任务重,C++ primer不能丢。因此,准备一波C++ primer深入阅读计划。

C++ primer 主要分为四个大的部分:

  • C++基础
  • C++标准库
  • 类设计者的工具
  • 高级主题

这个系列的复习将从C++基础开始,着重复习自己之前忘记或者不清楚的地方,C++11新的标准也加入了一些新的语法,需要熟练掌握,力求深入分析。此后准备阅读侯捷大神的《深入探索C++对象模型》这本书。路漫漫其修远兮,吾将上下而求索。

变量和基本类型

2.1基本内置类型

包括算数类型空类型(void)

算数类型包括:

字符、整数、浮点数、布尔值

  • .字符类型根据尺寸大小,分为宽字符、普通字符,普通字符(char)8位,宽字符有多种。

  • .整数类型如下:

类型含义最小尺寸
short短整形16位
int整形32位
long long长整型64位
  • .浮点类型如下:
类型含义最小尺寸
float单精度6位有效数字
double双精度10位有效数字
long double扩展精度10位有效数字

整形又可以分为带符号数(signed)无符号数(unsigned)

它们的区别在于带符号数需要使用最高位作为符号位,而无符号数不用,因此可以推断

signed int范围是 2312311 , 最大是2147483647

unsigned int范围是 02321 ,一般的,涉及到位运算是,因为有右移运算符,所以最好使用unsigned类型

字面值常量

一个型如42的值就被称作字面值常量,注意,它是一个常量。另外,它也有类型,根据形式和值决定了它的数据类型。

举例:

20 /* 十进制*/; 024 /* 八进制*/; 0x14 /* 十六进制 */

3.1415; 3.1415E0; 0.; 0e0; .001;

‘a’ // 字符字面值

“Hello world” // 字符串字面值, 需要提一下的是,字符串后面的空字符’\0’, 不要忘了

转义序列

最后我们可以指定字面值的类型,比如 L’a’ // 宽字符

1E-3F //单精度


2.2 变量

最重要的是初始化,初始化和赋值有区别:
初始化指的是对象在创建时的获得的一个值; 而赋值是把对象当前的值擦除,然后用新值替代。然而这个区别有啥用,暂时没用。直接上例子:

int units_sold = 0;
int units_sold = {0}; // 列表初始化
int units_sold{0};
int units_sold(0);  //不是一个函数声明

需要注意的是,列表初始化执行隐式转换时,如果存在丢失信息的危险,转换未执行。

1. 默认初始化

重点来了。如果变量定义时没有指定初值,则变量执行默认初始化。

  1. 定义在任何函数之外内置类型,默认初始化为0
  2. 定义在函数体内部内置类型,将不被初始化(是不确定的值)
  3. 类类型各自决定其初始化对象的方式。

2. 变量声明和定义

C++支持分离式编译,即可以将程序分成若干文件,每个文件独立编译。那文件之间需要共享代码和变量。因此就需要声明和定义。

声明(类型+名字):使名字为程序所知,要使用名字必须要对名字进行声明。使用 extern 关键字

定义(类型+名字+初始化):创建与名字相关联的实体。

例子:

extern int i; // 声明i,i在别处定义
int j; // 定义

extern double pi = 3.1415; // 定义而非声明,因为有显示初始化

注意:变量只能定义一次,但可以被声明多次。


2.3复合类型

复合类型有几种,此处介绍两种:引用指针

1.引用

引用可以理解成,为对象起了另外一个名字。那么,引用本身并非对象,它只是为已经存在的对象起另外一个名字。因此,所有围绕引用的操作都是在它绑定的对象上操作。

int ival = 1024;
int &refVal = ival; // 注意,引用必须初始化

2.指针

指针是一个对象,保存的是另一个对象的地址,因此实现了对其他对象的间接访问。指针不需要定义时赋初值。

int ival = 42;
int *p = &ival; // &在这里是取地址
*p = 1023;
double *a; // 可以不初始化
int *p1 = nullptr; // 空指针,养成习惯,每次定义指针时设置成初值,或者空指针
int *p2 = 0; // 也是空指针
int *p3 = NULL; // 同上,NULL是预处理变量(编译开始阶段),在cstdlib头文件中定义
int zero = 0;
p = zero; // 错误,这里是赋值,不能把int变量给一个指针类型

void *pv = &obj; // void* 指针可以存放任意对象的地址

int *&a = p; // a 是指针p 的一个引用

2.4 const限定符

const变量是常量,程序里无法改变这个值,于是方便对一个常量进行调整,而不用担心程序运行过程会改变它的值。

const对象一旦创建就无法修改

const int i = get_size(); // 运行时初始化
const int j = 3; // 编译时初始化
const int k; // 错误, k未经过初始化,必须初始化

默认情况下,const对象仅在文件内有效,多个文件中存在同名的const对象时,它们是相互独立的。

如果要在多个文件中共享const对象,那不论是定义还是声明都要加上extern关键字

//a file
extern const int i = fcn();
//b file
extern const int i;

1.const的引用

把引用绑定到const对象上,就叫对常量的引用。不能通过常量引用修改绑定的对象。另外,非常量引用不能绑定到常量对像,但是常量引用可以绑定常量对象,也可以绑定非常量对象。

int i = 42;
const int &r1 = i; // 正确,允许const引用绑定到普通对象
const int &r2 = 42; // 字面值常量
const int &r3 = r1 * 2; // 正确,建立了一个临时常量
int &r4 = r1 * 2// 错误,r4是一个非常量引用,不能绑定常量对象

i ++; // r1 随i变化,但是不能通过 r1 改变指向的对象

double a = 3.14;
const int &ri = a;
a = 4.13; // 这里ri指向的是一个临时变量,修改a,ri指向的值不变

2.指针和const

两种情况

指针指向一个常量对象(指向常量的指针)

const int i = 0;
const int *p = &i;
int j = 1;
p = &j; // 正确,可以对指针进行赋值,但是不能通过指针修改指向的对象

常量指针,即指针本身是一个常量(常量指针)

int i = 0;
int *const p = &i;

const double j = 3.12;
const double *const p1 = &j;

int h = 1;
p = &h; // 错误,常量指针不能进行赋值,但是可以通过指针修改指向的对象

3.顶层const,底层const

其实,顶层的意思就是对象本身是一个常量。底层的意思是引用或者指针指向或绑定的对象是一个常量

记住一句话

常量量指针或常量引用可以指向常量对象,也可以指向非常量(注意临时对象)

指向非常量的指针或者绑定非常量的引用不能指向或绑定常量对象

4.constexpr 和 常量表达式

感觉用处不大


2.5 处理类型

1. 类型别名

  • typedef 关键字
typedef Sales_item SI; // 类类型 
typedef long long LL; // 长整形
typedef int *const const_point; // 指针
typedef int (*func_point)(int a, int b); // 函数指针
  • using 关键字
using SI = Sales_item;
using LL = long long;
using const_point = int *const;
using func_point = int(*)(int, int);

注意

const + 类型别名时,const 修饰的是类型本身,不是复合类型指向的对象

typedef char *pstring;
const pstring cstr = 0; // 指向char 的常量指针
const pstring *ps; // ps是一个指针,它的对象是指向char 的常量指针
// 注意,这里不等于const char *cstr

2. auto 类型说明符

auto关键字的意思是,编译器分析变量类型,而不用显示说明变量类型。但是,auto修饰的变量必须要初始化。

vector<int> arr;
for (auto element : arr) {
    cout << element << endl;
}

3. decltype 类型指示符

场景是,想使用某个表达式推断出要定义的类型,但是并不想用该表达式的值初始化变量。

decltype(f()) sum = x; // sum 是f函数的返回类型

int i = 10;
decltype((i)) d; // 错误,括号里面是一个表达式,d是 int &,必须要初始化
decltype(i) e; // 正确,括号里面是一个变量,d是 int

注意

decltype((varible))的结果永远是引用

decltype(varible)的结果根据varible的类型来判断

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值