C++:内联函数,auto关键字,基于范围的for循环,指针空值nullptr

内联函数

在C语言中比较短小并可能多次使用的函数则会把它定义为宏函数
例如,我们定义一个加法的宏函数:

#define Add(a,b) ((a)+(b))

宏函数的优点:

  1. 没有压栈开销(因为在预编译的过程中编译器会完成宏函数的替换)
  2. 可以增强复用性(比如宏常量,改动的时候只需要改动一处即可)

宏函数的缺点:

  1. 复杂,导致代码可读性差,可维护性差,容易误用
  2. 不能进行调试
  3. 没有类型安全的检查

那么在C++中如何解决这种问题呢?
在C++中用enum、const来代替宏常量。用内联函数来代替宏函数。

1.内联函数的使用(在函数前面加上inline)
inline int Add(int a,int b)
{
	return a+b;
}
2.内联函数的特点
  1. 内联函数是一种以空间换时间的方法,省去了调用函数时的压栈开销,在使用该函数的位置直接进行展开。
  2. 内联函数对编译器来说只是一个建议,如果函数代码较短时,编译器会接受你的建议,如果函数代码较长或者是循环、递归等函数,编译器会自动优化。
  3. 内联函数不可以声明和定义分离,这样会导致链接错误,因为内联函数没有地址,它只是在使用的地方直接展开。

auto关键字(C++11)

auto是C++11里引入的新型语法,它是自动推导变量的类型
例如:

int a=10;
auto ra=a;

这里编译器会根据a的类型自动将auto推导为int,因此ra的类型也是int。
输出ra的类型可以用下方语句:(输出为int)

cout<<typeid(ra).name()<<endl;

接下来看一段代码,分析auto推导出的类型是什么:

int main()
{
	int x = 10;
	auto y = 'c';
	auto a = &x;
	auto* b = &x;
	auto& c = x;
	cout << typeid(y).name() << endl;//char
	cout << typeid(a).name() << endl;//int*
	cout << typeid(b).name() << endl;//int*
	cout << typeid(c).name() << endl;//int
	return 0;
}

y前面的auto会推导为char
a前面的auto会推导为int*,a的类型为int*
b前面的auto会推导为int,b的类型为int*(因为这里有一个*,所以auto只需要充当int即可)
c前面的auto会推导为int

auto特点
  1. 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
  2. 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量
  3. auto不能充当函数参数(因为调用函数要开辟函数栈帧,用auto则不知道函数栈帧开多大)
  4. auto不能声明数组(数组在进行声明时我们也需知道数组的大小,用auto就不知道数组有多大)
  5. 当涉及到变量的类型书写起来特别长时,可以使用auto,书写简单方便(例如map,迭代器等)

基于范围的for循环(C++11)

C++11中,引入一种新式for循环遍历数组时会非常方便。
for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围

int array={1,2,3,4,5};
for(auto e:array)
	cout<<e<<endl;

这里就是让e依次去取array里的数据,然后进行输出,就完成了数组的遍历。
注意:

  1. 与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环
  2. for循环迭代的范围必须是确定的。 对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围
  3. 迭代的对象要实现++和==的操作

指针空值nullptr(C++11)

在C++98中,空指针我们通常定义为NULL,但是实际上NULL是一个宏,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量,因此可能会出现一些问题,例如:

void f(int)
{
	cout<<"f(int)"<<endl;
}
void f(int*)
{
	cout<<"f(int*)"<<endl;
}
int main()
{
	f(0);//调用f(int)
	f(NULL);//调用f(int)
	f((int*)NULL);//调用f(int*)
	f(nullptr);//调用f(int*)
	return 0;
}

f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的初衷相悖,所以C++11里引入指针空值nullptr,nullptr代表一个指针空值常量

注意:

  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr

你可能感兴趣的:(C++)