第二章 变量和基本类型


简介

C++Primer第五版学习记录,主要是记录一些之前不太注意的地方。目前是第二章 变量和基本类型。


一、关于基本类型

除了扩展的char和bool类型,其它均有符号signed和无符号unsigned。
但需注意的是,char类型是否有符号取决于编译环境,可移植时要注意。

二、关于转义序列

不可打印、特殊含义字符需要通过转义序列。

//普通型
\t 
\b 
\n
//泛化十六进制,可以多个
\x
//泛化八进制,1、2、3个
\12

三、关于变量

1.初始化和赋值

初始化和赋值严格来说并不相同,可以简单理解初始化是无中生有,赋值是改邪归正。虽然大多时候区别没有意义
C++11支持了列表初始化,即通过{}初始化,但需要注意的是,若该方式会导致初始值丢失信息时,编译会报错。个人理解是更加严格。

long double ld = 3.1415926536;
int a{ld},b = {ld};//编译报错
int c(ld),d = ld;//正确

初始化分为值初始化和默认初始化,具体的初始化方式取决于数据类型和位置
(1)内置类型:
函数体外定义内置类型时,执行默认初始化,被初始化为0或’’

#include <iostream>

using namespace std;
  
int i;
double d;
bool b;
char c;
  
int main() {
  cout << "i = " << i << endl;            // 0
  cout << "d = " << d << endl;            // 0
  cout << "b = " << b << endl;            // 0
  cout << "char" << c << "char" << endl;  // char char
  
  return 0;
}

函数体内定义时默认初始化,此时值是未经过初始化的未定义值。使用未定义值会导致不可控的结果。而且编译器也不一定能够确定发现错误。例外是使用static定义静态局部变量时,会默认初始化为0。

#include <iostream>
 
using namespace std;
 
int main() 
{
	int i;
	static int j;
	cout << "i = " << i << endl;//随机值或是无法编译
    cout << "i = " << i << endl;//0
    
	system("pause");
	return 0;
}

(2)类类型
当使用默认构造函数,而且类成员要没有类内初始值,类才会执行默认初始化,否则根据构造函数决定初始化类型。

2.声明和定义

此处需注意的是,仅声明而非定义,前加extern
若是多个文件内使用同一变量,则定义时前加extern

3.引用和指针

个人理解引用类似取别名,不是实际存在的对象;指针则是真实存在的对象。
引用的赋值,实际理解为绑定。又由于引用本身的作用,因此必须被初始化,即定义时即绑定一个对象。

4.const和constexpr

4.1对const的理解

const的作用是限制写。
对于指针符合类型,又区别为顶层const和低层cosnt,顶层限制指针本身,即常量指针,const放在*之后;底层限制指针所指对象,即指向常量的指针,const 放在*前,与基本类型的位置无关。
最核心的就是,拷贝时,无法将一个常量对象拷贝给一个非常量的指针(引用)。

const int i = 42;
int &r = ci;//错误
int *p = &i;//错误

与变量类似,若需跨文件声明const变量,定义时也要加extern,否则每个文件内的const会被认为是不同的变量。

4.2 constexpr和常量表达式

常量表达式的概念:在编译期就可以计算出结果的表达式。
常量表达式的好处:
  1.允许一些计算只在编译时进行一次,而不是每次程序运行时;
  2.编译器可以进行尺度更大的优化;
  3.可以用在需求编译期间常量的上下文,例如数组长度等;
 总之,如果想认定一个变量是常量表达式,则声明成constexpr即可。
constexpr也可以修饰指针,放在*前,但只能修饰指针本身,作为顶层效果。初始值必须是nullptr、0或者存储于某个固定地址中的对象。

int j = 0;
const int i = 42;
constexpr const int *p = &i;
constexpr int *q = &j;

四、关于处理类型

1. 类型别名

C语言中,类型别名通过关键字typedef,C++11新标准提供了一种新的方法,using。

typedef double wages;
typedef wages *p;
using SI = Sales_item;

需要注意的是,当与复合类型结合,尤其是指针与常量时,不能当做简单替换来理解。

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

例如,上例中cstr实际上是一个常量指针,并非指向常量的指针(与astr不一样)。造成这种结果的原因是,此时的基本数据类型为指针类型,而非char类型,所以const修饰的对象是不一样的。

2.auto类型

auto时编译器推断的类型取决于初始值的类型,但可能不完全一致。
可以一行定义多个变量,但基本类型必须相同

auto m = 0,*n = &m//p是整型指针,i是整型
int &p = m;
auto q = p;//虽然p是整型引用,但auto取决于使用的对象,即m的类型。

auto会忽略顶层const,保留低层const

const int i = 1,&j = i;

auto a = i, b = j;//注意:此时a、b都是整型变量,而非常量!

auto c = &i;//c是指向整型常量的指针

如果需要顶层const,则需明确指出

const auto k = i;//k是整形常量

对于引用而言,并不存在顶层const,低层const会被正常保留

auto &d = i;//d是整型常量引用
auto &e = 42;//错误,因为42是字面值,而e是非常量引用
const auto &f = 42;//正确

3.decltype类型

个人理解,该类型是针对表达式类型的auto,更加贴近于表达式本身的类型(包括顶层和低层const),且由编译器推断,不需要求出表达式的值

const int i = 0,&j = i;
decltype(j) x = i;//x是整型常量引用,此处不是看的引用的对象,而是引用本身
decltype(j) y;//错误,引用必须初始化

比较特别的是,关于对于指针和表达式的处理

int i = 0,*p = &i,&q = i;
decltype(*p) x = i;//此时的x是引用
decltype((i)) y = i;//y也是引用

当变量本身加了一层或者多层括号时,会被当成引用来处理。

五、关于class和struct

此处只比较两者在继承上的区别,class是private,struct是public


总结

关于这一章主要是一些基础知识,关于const、constexpr、auto、decltype的相关概念
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值