一、命名空间:
使用命名空间的目的:在C++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称都将存在于全局作用域中,可能会导致很多冲突。使用命名空间对标识符的名称进行本地化,以避免命名冲突或名字污染,关键字namespace。
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后**接一对{}**即可,{}中即为命名空间的成员。
// 1. 普通的命名空间
namespace N1 // N1 为命名空间的名字
{
// 命名空间中既可以定义变量,也可以定义函数
int a;
void func()
{
return;
}
}
// 2.命名空间可以嵌套
namespace N2
{
int a;
int b;
void func()
{
return;
}
namespace N3
{
char c;
double d;
int func()
{
return 0;
}
}
}
// 3. 同一个工程中允许多个相同名字的命名空间
// 编译器最终会将相同名字的命名空间合成一个
namespace N1
{
int func(int a)
{
return 1;
}
}
***注:***一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
二、命名空间的使用
使用命名空间有三种方式:
1.命名空间名称加作用域限定符
2.使用using将命名空间中的成员引入
3.使用using namespace将命名空间引入
***注***推荐使用第二种方式,使用什么变量引入什么变量
三、C++的输入输出
C++的输入与输出在使用中,需要包含头文件,输入关键字cin,输出关键字cout;例:std::cin>>a; std::cout<<a<<endl; endl的作用为换行(如同在C中的"\n")。C++在使用输入输出时更加方便,不需要像C中的printf与scanf一样添加格式化输出(%d, %f 等)。
#include <iostream>
using namespace std;
int main()
{
cout << "hello world!" << endl;
}
四、缺省参数
缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。(在函数的参数中设置默认值)
缺省参数可以是全缺省或半缺省,需要注意半缺省时,参数默认值从右向左设置。默认值的设置在声明和 定义中只能出现一处(如果声明和定义同时出现,恰巧两个位置提供的值不相同,那编译器就不知道用哪一个缺省)。
作用:在有实参时使用实参,没有实参使用默认值。
注:缺省值为常量或者全局变量。C不支持缺省(编译器不支持)。
// 全缺省
int TestFunc(int a=0, int b = 0, int c = 0)
{
return a + b + c;
}
//半缺省
int TestFunc(int a, int b = 0, int c = 0)
{
return a + b + c;
}
五、函数重载
C++允许在同一作用域中声明几个功能类似的同名函数,但这些函数的形参列表(参数个数或类型或顺序)必须不同(命名方式不同,C++可以区分)。常用来处理功能类似数据类型不同的问题。
例:下面两个函数构成重载吗?
// 函数重载
short Add(short left, short right)
{
return left + right;
}
int Add(short left, short right)
{
return left + right;
}
答:不属于,函数重载的要求是同名函数的参数列表不同,返回值的类型不同,并不能构成重载。
想使用C的命名规则:extern “c” {}
C语言中为什么不能构成函数重载?
答:在C中的变量或函数的命名规则是在名字前加_,所以相同函数命名完成后还是相同的名字,编译器不能识别,所以不能构成函数重载。
六、引用
引用不是定义一个新的变量,而是给已存在的变量取一个别名。
引用类型与实体的类型相同;引用在定义时必须初始化;一个变量可以有多个引用;引用初始化完成后,不可以引用其他实体;引用不开辟内存空间,与引用的变量共用一块内存空间;引用是对已存在变量取了一个别名。
类型& 引用变量名(对象名)== 实体
使用场景:
1.做参数
与指针比较,比指针访问方便,引用相当于变量本身,指针需要开辟空间保存变量地址。
//做参数
void Swap(int& left, int& right)
{
int tmp = left;
left = right;
right = tmp;
}
2.做返回值
直接返回实体运算后的结果
int& Ref(int& a)
{
return a += 10;
}
注:如果函数返回时,离开函数作用域后,其站上空间已经还给系统,因此不能用栈上的空间作为引用类型返回。如果以引用类型返回,返回值的生命周期必须不受函数的限制(即比函数生命周期长)。
传引用的效率大于传值的效率
引用和指针的区别:
在底层实现上,引用仍然是用指针所实现的。
- 引用在定义时必须初始化,指针没有要求;
- 引用在初始化时,引用一个实体后,不能引用其他实体;指针再任何时候可以指向同类型的实体;
- 没有NULL引用,但有NULL指针;
- 在 sizeof 中:引用的大小为类型的大小,指针为地址空间所占字节个数(32位平台下占4个字节);
- 引用自加即为引用实体加一,指针自加即为指针向后偏移一个类型的大小;
- 有多级指针,没有多级引用;
- 访问的实体不同,指针需要显式解引用,引用编译器自己处理;
- 引用比指针使用起来更安全。
七、内联函数
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。
inline是一种以空间换时间的做法,省去调用函数的开销。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数。
inline对于编译器只是一个建议,编译器会自动优化。
inline不建议声明和定义分离,分离会导致链接错误。
宏的优缺点:
优点:1. 增强代码的复用性;2.提高性能
缺点:1. 不方便调试宏;2. 导致代码可读性差,可维护性差,容易误用;3. 没有类型安全的检查
C++有哪些技术替代宏?
答:1. 常量定义换用const; 2. 函数定义换用内联函数
八、auto关键字(C++11)
早期auto修饰的变量是具有自动存储器的局部变量;
(C++11)auto作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器自己在编译时期推导而得。(auto需要进行初始化)
auto并不是一种“类型”的声明,而是一个变量声明的“占位符”,编译器会在编译时期将auto替换为变量实际的类型。
auto在声明指针时,auto与auto*没有区别;在声明引用时,必须+&(auto&);在同一行定义多个变量时,类型必须相同,因为编译器在推导时,只推导第一个变量,用推导出来的类型定义其他变量。
auto不能推导的情景:
- auto不能作为函数的参数;
- auto不能直接用来声明数组。
九、基于范围的for循环
在C++98中遍历一个数组,可以按照以下方法遍历:
void TestFor()
{
int array[] = {1, 2, 3, 4, 5};
int size = sizeof(array) / sizeof(array[0]);
for(int i = 0; i < size; i++)
{
array[i] *= 2;
}
for(i = 0; i < size; i++)
{
cout << array[i] << " ";
}
}
基于范围的for循环(C++11)
for(①auto& e : ②array)
{
e *= 2;
}
①. 范围内用于迭代的变量
②. 表示被迭代的范围
范围for循环的使用条件:
- for循环迭代的范围要确定(数组就是数组中第一个元素和最后一个元素,类需要实现begin和end方法),需要注意的是数组在传参后退化为指针,不能确定范围。
- 迭代的对象要是想++,–操作(运算符重载)
十、 指针空值nullptr(C++11)
C++98中NULL会被定义为字面值常量0,或无类型指针(void*)0,避免混淆C++11中引入了关键字nullptr。无头文件,类型为nullptr_t,字节数占用与指针相同(32位操作系统下为4个字节),为了提高代码的健壮性建议使用nullptr。
本节到此结束,
学习编程,兴趣是必不可少的,如果想提高自己的代码水平,一定要多想多练习。
菜鸡刚开始学习,可以交流,有问题可留言╭(╯^╰)╮
可关注我,持续更新。