C++Primer——《第二章》 变量与基本类型

本文详细介绍了C++中的变量与基本类型,包括数据类型的选择、变量的声明与定义、C++关键字、作用域、引用与指针的区别、指针的使用、const常量的规则、constexpr与常量表达式、类型别名以及auto和decltype类型说明符的运用。内容深入浅出,适合C++初学者和进阶学习者。
摘要由CSDN通过智能技术生成

目录

如何有效的选择数据类型 (32P)

默认初始化(40P)

可以使用 extern 关键字声明一个变量而非定义它 (41P)

变量能且只能被定义一次, 但是可以声明多次 (41P)

C++ 中的关键字 (43P)

名字的作用域 (43P)

引用与指针的区别 (47P)

用 nullptr、NULL、0 来初始化指针为空 (48P)

void* 指针 (50P)

 指向指针的指针 —— 二级指针 (52P)

绑定到指针的引用 和 指向引用的指针(52P)

如何阅读 “ int *&r = p; ”  这样的变量声明 (53P)

const 常量的初始值可以是任意复杂的表达式 (53P)

默认情况下, const对象 被设定为仅在所在的文件内有效 (54P)

如果想在多个文件之间共享 const 对象, 必须在该变量的不管是声明还是定义都需要添加 extern 关键字 (54P)

*const 引用 (54P)

指向常量的指针(56P)

const 指针 (56P)

顶层const (57P 191P)

什么叫常量表达式 (58P)

 constexpr 变量 (59P)

 constexpr 函数

哪些是字面值类型能作为 constexpr 类型的初始值 (59P)

 constexpr和指针 (59P)

使用  typedef、using 给类型起别名 (60P)

指针、常量和类型别名

auto 类型说明符 (61P)

复合类型、常量 和 auto 

decltype 类型说明符 (62P)

decltype 和引用


如何有效的选择数据类型 (32P)


默认初始化(40P)


可以使用 extern 关键字声明一个变量而非定义它 (41P)


变量能且只能被定义一次, 但是可以声明多次 (41P)


C++ 中的关键字 (43P)


名字的作用域 (43P)


引用与指针的区别 (47P)


引用与指针的区别:

  •   指针本身就是一个对象(或实体),允许对指针复制和拷贝, 而且在指针的生命周期内它可以先后指向几个不同的对象。但是引用并不是一个对象,只是一个已经存在的对象所起的别名。
  •  指针无需在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有初始化,也将拥有一个不确定的值。但是 引用必须初始化
  •  引用使用时无须解引用(*),指针需要解引用。
  •  引用只能在定义时初始化一次,之后不能改变指向其他变量(从一而终),指针变量可以指向其他不同的对象。
  •  引用必须指向有效的变量,指针可以为空,引用不能为空。
  •   sizeof 指针对象和引用对象的意义不一样, sizeof 引用得到的是所指向变量(对象)的大小。
  • 而sizeof 指针本身的大小,即所指向的变量或对象的地址大小。
  •   指针和引用自增自减的意义不一样。
  • 从内存分配上看,程序需要为指针变量分配内存区域,而引用不需要分配内存区域。
  •  相对而言,引用比指针更加安全。
  •   使用指针比引用灵活,但是其风险也很大,使用指针时一定要检查指针是否为空(NULL), 且内存空间回收后,指针是否置零,以免野指针的发生,发生内存泄漏。

相同点:

  •  两者都是地址的概念,指针指向一块连续的内存空间,其内容为所指内存的地址,引用是某块内存的别名。
  •  指针可以 指向数组的地址来代替数组使用,而引用不可以代替数组引用只能指向数组中的某一个元素。

注意:返回的引用不能指向超出作用域范围的对象,这些对象在函数结束后、将不存在,这是不合法的,不要返回局部变量的引用。

注意: 因为引用不是对象, 没有实际地址, 所以不能定义指向引用的指针。(52P)

注意: 一般情况下:其他所有引用的类型都要和与之绑定的对象严格匹配。而且,引用只能绑定在对象上, 而不能与字面值或某个表达式的计算结果绑定在一起。

int  &refVal4=10;  //错误:引用类型的初始值必须是一个对象
double dval=3.14;
int &refVal5=dval;  //错误:此处引用类型的初始值必须是int型对象

用 nullptr、NULL、0 来初始化指针为空 (48P)


void* 指针 (50P)


 指向指针的指针 —— 二级指针 (52P)


绑定到指针的引用 和 指向引用的指针(52P)


引用本身不是一个对象,因此不能定义一个指向引用的指针。 但是指针是对象, 所以可以把一个引用 绑定在 一个指针上。

int main()
{
	int i = 42;
	int a = 100;
	int* p =&a ;
	int *&r = p;  // r 是对指针p 的引用
	cout << "输出r 所引用的值:" << *r << endl;

	r = &i; // r 现在重新指向了一个对象
	cout << "再次输出r 所引用对象的值:" << *r << endl;
	*r = 0;
	system("pause");
	return 0;
}

如何阅读 “ int *&r = p; ”  这样的变量声明 (53P)


const 常量的初始值可以是任意复杂的表达式 (53P)


默认情况下, const对象 被设定为仅在所在的文件内有效 (54P)


如果想在多个文件之间共享 const 对象, 必须在该变量的不管是声明还是定义都需要添加 extern 关键字 (54P)



*const 引用 (54P)


通常,引用的类型必须与其所引用对象的类型一致,但是有两个例外:

  •   第一个是在初始化常量引用时允许用任意表达式作为初始值, 只要该表达式的结果能转换成引用的类型即可。 尤其, 允许为一个常量引用绑定非常量的对象、字面值,甚至是个一般表达式:
int i = 42;
const int &r1 = i;  //允许将const int& 绑定到一个普通int对象上
const int &r2 = 42; //正确 const引用
const int &r3 = r1*2; //正确 const 引用
int &r4 = r1 * 2; // 错误: r4 是一个普通的非常量引用

double dval = 3.14;
const int& r4 = dval; // 正确, dval 是double 类型的值可以转换为 int 类型
int& r5 = dval; // 错误, 普通引用必须与绑定的对象具有相同的类型
int main()
{
	double dval = 3.14;
	const int& r4 = dval; // 正确, dval 是double 类型的值可以转换为 int 类型
	cout << dval << " " << r4 << endl;
	dval = 99.6;
	cout << dval << " " << r4 << endl;
	system("pause");
	return 0;
}

输出结果为:

3.14 3
99.6 3

该段程序与我们预期的不相符, 当我们 运行到  dval =  99.6;  这条语句时,输出的结果应该是 99.6、99.6 才对, 为啥是 99.6、3 ?

因为 r4 引用的是一个 int 型的数。对 r4 的操作应该是整数运算, 但是 dval 却是一个双精度数而非整数。 所以为了确保让 r4 绑定到一个整数, 编译器把上述代码变成了如下:

const  int temp = dval; // 由双精度浮点数生成一个临时的整型常量
const int &r4 = temp; // 让r4 绑定到这个临时量
  • 在这种情况下, r4 绑定了一个临时量 (temporary) 对象。所谓临时量对象就是当编译器需要一个空间来暂存表达式的求值结果时临时创建的一个未命名的对象。
  • 因为实际上 r4 绑定到的是一个临时量,  所以当我们运行 dval = 99.6 时, 真正改变的是 r4 所绑定的 临时量而已,因此并没有改变 r4 的值,所以输出的是 99.6、3。

当我们把 引用的类型改为与引用对象一致的时候,输出的结果与我们预期相符:

int main()
{
	double dval = 3.14;
	const double& r4 = dval; // 正确, dval 是double 类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值