C++学习笔记1

继续本周的C++学习任务。

C语法的增强及对应的C++特性

引用、[C++11]空指针与动态内存分配

引用Reference

引用就是另一个变量的别名,通过引用所做的读写操作实际上是作用于原变量上。

1
2
int x;
int& rx=x;

C++指针与引用符号应靠近其类型名而非名字。

引用可以作为函数参数,但调用时只需要传递普通变量即可。在被调用函数中改变引用变量的值,则改变的是实际参数的值。

空指针和动态内存分配

1.空指针

1.1 0带来的二义性问题

  1. C++03中,空指针使用“0”来表示。0既是一个常量整数,也是一个常量空指针。
  2. C语言中,空指针使用(void *)0来表示
  3. 有时候,用“NULL”来表示空指针(一种可能的实现方式是#define NULL 0)

1.2 C++标准化委员会希望“空指针”是一个确定的东西。
C++11中引入保留字“nullptr”作为空指针

2.动态内存管理:分配/释放

2.1 C++中通过运算符new申请动态内存

1
2
new  <类型名> (初值) ;     //申请一个变量的空间
new <类型名>[常量表达式] ; //申请数组

如果申请成功,返回指定类型内存的地址;
如果申请失败,抛出异常,或者返回空指针(nullptr)。(C++11)

2.2. 动态内存使用完毕后,要用delete运算符来释放。

1
2
delete   <指针名>;    //删除一个变量/对象
delete [] <指针名>; //删除数组空间

数据类型与转换、列表初始化

布尔类型

逻辑运算符和C语言基本一致

注:编码规范:布尔变量/函数的命名应使用前缀“is”,断行必须很明显,在逗号或运算符后换行,新行要对齐

列表初始化

列表初始化是C++11的一个新特性,“列表”是用花括号括起来的一(些)值。

列表初始化分为两类:

  • 直接列表初始化
  • 拷贝列表初始化
1
2
3
4
5
6
7
8
//直接列表初始化)
/* Variable initialization */
int x{}; // x is 0;
int y{ 1 }; // y is 1;
/* Array initialization */
int array1[]{ 1,2,3 };
char s1[ 3 ] { 'o', 'k' };
char s3[]{ "Hello" };
1
2
3
4
5
6
7
8
//拷贝列表初始化
/* Variable initialization */
int z = { 2 };
/* Array initialization */
int array2[] = { 4,5,6 };
char s2[] = { 'y','e','s' };
char s4[] = { "World" };
char s5[] = "Aloha"; // Omit curly braces (省略花括号)

尽量使用列表初始化,列表初始化不允许丢失数据精度的隐式类型转换。

类型转换

类型转换有两种:

1.隐式类型转换

  • 由编译器按照数据类型的转换规则自动转换,无需程序员干预。
  • 可能导致数据精度损失,或者转换失败。
  • 应尽量避免使用隐式类型转换

2 显式类型转换(即:强制类型转换)

  • 由程序员用明确的类型转换语法写出类型转换代码。
  • 好处是,程序员知道自己要做什么并且把这个想法明确表达出来。

C++风格强制类型转换:语法:static_cast value

编码规范:类型转换必须显式声明,永远不要依赖隐式类型转换。

自动类型推导:类型系统、auto与decltype

静态类型 v.s. 动态类型:

程序设计语言的类型系统机制会检查连接在一起的多个块的一致性

上述检查若发生在编译期,称为静态类型
上述检查若发生在运行时,称为动态类型
上述检查若同时存在于编译期和运行时,称为混合类型

自动类型推导:auto关键字

1.关键字auto

C++11中,auto关键字放在变量之前,作用是在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型。例如:

1
2
3
int a = 10;
auto au_a = a;
cout << typeid(au_a).name()endl;

2.auto的使用限制

1.auto 变量必须在定义时初始化,这类似于const关键字

1
2
3
auto a1 = 10;  //正确
auto b1; //错误,编译器无法推导b1的类型
b1 = 10;

2.定义在一个auto序列的变量必须始终推导成同一类型

1
2
auto a4 = 10, a5{20};   //正确 
auto b4{10}, b5 = 20.0; //错误,没有推导为同一类型

3.如果初始化表达式是引用或const,则去除引用或const语义

1
2
3
4
int a{10}; int &b = a;
auto c = b; //c的类型为int而非int&(去除引用)
const int a1{10};
auto b1 = a1; //b1的类型为int而非const int(去除const)

4.如果auto关键字带上&号,则不去除引用或const语意

1
2
3
4
int a = 10; int& b = a;
auto& d = b;//此时d的类型才为int&
const int a2 = 10;
auto& b2 = a2;//因为auto带上&,故不去除const,b2类型为const in

5.初始化表达式为数组时,auto关键字推导类型为指针

1
2
3
int a3[3] = { 1, 2, 3 };
auto b3 = a3;
cout << typeid(b3).name() << endl; //输出int * (输出与编译器有关)

6.若表达式为数组且auto带上&,则推导类型为数组类型

1
2
3
int a7[3] = { 1, 2, 3 };
auto& b7 = a7;
cout << typeid(b7).name() << endl; //输出int [3] (输出与编译器有关)

7.C++14中,auto可以作为函数的返回值类型和参数类型


C++学习笔记1
https://chujian521.github.io/blog/2020/02/20/C-学习笔记1/
作者
Encounter
发布于
2020年2月20日
许可协议