C++慕课学习第三单元
北京邮电大学
C++程序设计(面向对象进阶)
崔毅东
1. 引用、空指针、及内存动态分配
Reference
定义 :A reference is an alias for another variable. (引用就是另一个变量的别名)
声明引用变量的方法
int x;
int& rx = x;//本质上是被引用对象的类型使用&符
//-----------
或者
int x, &rx = x;
性质 :
- 通过引用所做的读写操作实际上是作用于原变量上。
- 引用必须在声明的时候初始化。
- 引用一旦初始化,引用名字就不能再指定给其他变量。
例子:
//pass by reference
void swap(int& x,int& y)
{
int t;
t = x; x = y; y = t;
}
int main()
{
auto a{5},b{10};
cout << "Before: a = " << a <<" b = " << b << endl;
swap(a,b);
cout<< "Now: a = " << a <<" b = " << b << endl;
return 0;
}
输出结果:输出结果:
Before: a=5 b=10
After: a=10 b=5
补充
int a { 0 }, b { 1 };
int& r { a }; // 引用变量 r 在声明的同时就要初始化,r是a的别名
r = 42; // 相当于 a = 42
r = b; // 相当于 a = b; 执行后 a 的值是1
// 此处不是让r变成b的引用
// 引用r声明并初始化后,r就不能再改为其它变量的引用
int& r2 = a; // 继续给a起别名
int& r3 = r; // 声明引用变量 r3,用r初始化
// 这个相当于 int& r3 = a; 因为 r 是 a 的别名
//常量指针类型引用,前面的const不可省掉
const char* s = "Hello";
const char*& rs = s;
动态内存管理:分配/释放
- C++中通过运算符new申请动态内存
new <类型名> (初值) ; //申请一个变量的空间 new <类型名>[常量表达式] ; //申请数组
如果申请成功,返回指定类型内存的地址; 如果申请失败,抛出异常,或者返回空指针(nullptr)。(C++11)
- 动态内存使用完毕后,要用delete运算符来释放。
delete <指针名>; //删除一个变量/对象 delete [] <指针名>; //删除数组空间
2.数据类型与转换,[C++]列表初始化
-
布尔数据类型(Boolean data type)
C++语言在其标准化过程中引入了**bool**、**true**和**false**关键字,增加了原生数据类型来支持布尔数据。 布尔类型的大小(所占的存储空间)依赖于具体的编译器实现。也可以用 sizeof运算符得到其占用的空间
-
布尔类型的用途
布尔数据类型主要与条件语句相关。条件语句用来更改程序控制流。
-
C++中的布尔类型
C++ keyword: bool, true, false 例如: bool isMyBook; bool isRunning = {false}; //C++11 列表初始化方式 bool isBoy( ); bool hasLicense(); bool canWork(); bool shouldSort();
-
布尔类型与整型的转换(Conversion between bool and int)
转换规则: 0 <--> false // 整数0和布尔false互相转化 true <--> 1 // 布尔true转化为整数1 non-zero <-->true // 任意非0整数转化为布尔true
-
关系运算得到布尔值
关系运算(Relational Operation)包括:==, !=, <=, >=, <, > 例如: int a=0, b={1}; //C++11 3 == a; b < a; 3.2 >= b; if (3 == a) { // blah blah }
-
逻辑运算得到布尔值
逻辑运算(Logical Operation)包括:&&, ||, ! int a={0}, b{1}; //C++11 a && b; b || 18; !a; while (!a) { // blah blah }
-
代码示例
#include <iostream> int main() { bool isAlpha; isAlpha = false; if (!isAlpha) { std::cout << "isAlpha=" << isAlpha << std::endl; std::cout << std::boolalpha << //换行必须明显,在逗号或运算符后 "isAlpha=" << isAlpha << std::endl;//这个地方的引号对齐上一行的std } return 0; }
运行结果: isAlpha=0 isAlpha=false 注意:
-
编码规范
26. The prefix is should be used for boolean variables and methods. 26. 布尔变量/函数的命名应使用前缀“is” 例如:isSet, isVisible, isFinished, isFound, isOpen 39. The incompleteness of split lines must be made obvious. 39. 断行必须很明显。 在逗号或运算符后换行,新行要对齐
-
-
列表初始化(List Initialization)
-
Before C++11 (C++11标准之前的初始化方法)
int x = 0; int y(2); char c('a'); int arr[] = { 1,2,3 }; char s[] = "Hello"; C++11 also support the old ways (C++11标准仍然支持旧的初始化方法)
-
List Initialization (列表初始化)
- List initialization is a new feature for C++11 (列表初始化是C++11的一个新特性)
- List: braced-init-list (“列表”是用花括号括起来的一(些)值)
- 列表初始化的两个分类
1. Direct list initialization (直接列表初始化)
2. Copy list initialization (拷贝列表初始化)//直接列表初始化) /* 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" }; //拷贝列表初始化 /* 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 (省略花括号)
-
3.自动类型推导
auto :根据变量初始值自动匹配类型。
typeid(变量名).name //typeinfo头文件,返回变量名的类型
同一行必须是同一类的初始化。
eg: auto a{20},b{20.0}//不合法
auto不管& 和 const,但auto&是管&和const的
初始化表达式是数组时,退化为指针类型。若加上&即auto&,则成为原数组的引用。
C++14标准,auto可以作为函数返回值类型和参数类型。
*********************
当我们非常希望能够在变量定义的时候,【明确】地指出变量的类型,而且不希望随便更改其类型,那么我们可以使用下面的方法:
auto x = int {3}; // 初始化列表
auto y = int {3.0}; // 编译器报错,初始化列表不能窄化
auto z = int (3.0); // C风格的强制类型转换,z的值是整数3
要避免在一行中使用直接列表初始化和拷贝列表初始化,也就是,下面的代码是有问题的:
auto x { 1 }, y = { 2 }; // 不要同时使用直接和拷贝列表初始化
通过在数值后加上f表明是一个float类型的变量。
decltype:利用已知类型声明新变量。
decltype (fun()) x = fun();
decltype是在编译期推导一个表达式的类型,它只做静态分析,因此它不会导致已知类型表达式执行。
decltype 主要用于泛型编程(模板)