关于c++的笔记系列如何开始思考了好多,因为笔者对笔记系列博客的目的不仅是为了作为以后的复习方法,也有极大的目的是吸引阅读量,好为日后一些较高层次的文章做铺垫。但是,c++作为一门较难入门的语言来说,第二点暂且搁置。本文就简单按照笔者学习的顺序对一些重难点做出整理。
(❁´◡`❁)
前言
能看懂c++就能看懂C语言,能看懂C语言c++也一定能看懂多半。
本文主要整理一些如果在能看懂C语言的情况下,c++有哪些有趣的新事物。
认识一些琐碎的语法~~
一、命名空间
为了实现面向对象的编程思想,以及规避各种变量、函数和类的作用域冲突,目的是对标识符的名称进行本地化,以规避命名冲突或名字污染,namespace就是对这种问题产生的。
定义方法
命名空间既可以有定义变量,也可以定义函数
namespace o //o是命名空间的名称 { int a; int Add(int left, int right) { return left + right; } }
可以嵌套使用
namespace o2 { int a; namespace o3 { int b; } }
可以存在名称相同的命名空间,编译器会将其合并
namespace o { int sum(int left, int right) { return left - right; } }
一个命名空间只定义了一个新的作用域,内容仅限于该命名空间内。
使用方法
我们有这样一个命名空间
namespace N
{
int a = 10;
int b = 0;
int add(int left, int right)
{
return left + right;
}
int sub(int left, int right)
{
return left - right;
}
}
使用方法大概有如下几种
加命名空间名称及作用域限定符
int main() { printf("%d", N::a); return 0; }
使用using将命名空间成员引入
using N::b; int main() { printf("%d", N::a); printf("%d", b); return 0; }
使用using namespace将命名空间整块引入
using namespace N; int main() { printf("%d", N::a); printf("%d", b); add(10, 20); return 0; }
一个命名空间只定义了一个新的作用域,内容仅限于该命名空间内。
一个命名空间只定义了一个新的作用域,内容仅限于该命名空间内。
一个命名空间只定义了一个新的作用域,内容仅限于该命名空间内。
二、输入输出
c++理应有它独特的输出方式
代码如下
#include <iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
新朋友cout与cin分别名叫标准输出(控制台)和标准输入(键盘)
使用是必须包含iostream的头文件以及std的公共标准命名空间。
拓展:早期这两者都可以包含在一个.h文件中,后来为了使c++与C语言区分和更加标准化,不带.h且加上std
- 更方便的控制输出格式
int main()
{
int a;
double b;
char c;
cin >> a;
cin >> b >> c;
cout << a << endl;
cout << b << " " << c << endl;
return 0;
}
不需要增加数据格式控制
三,缺省函数
c++中,我们会看到函数定义或声明时发现将括号内的形参赋值的情况,称之为缺省,函数传参时如果有实参,则形参使用实参的值,如果没有实参,则使用缺省值
代码如下
void funcpp(int a = 0)
{
cout << a << endl;
}
int main()
{
funcpp(); //没有传参时,使用参数的默认值
funcpp(10); //传参使用指定指定的实参
}
几种不同类型
- 全缺省
void testa(int a = 10, int b = 20, int c = 30)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
- 半缺省
void testb(int a, int b = 20, int c = 30)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
-
结合函数传参理解,缺省只能从右向左缺省且不能间隔
-
缺省函数不能在申明与定义中同时出现
如果缺省值在生命与定义中同时出现,而且两个位置的缺省值并不相同,编译器无法确定使用哪个位置的缺省值。一般在声明处给出,方便修改
- 缺省值必须用常量或者全局变量
函数重载
c++有一些操作起来特别方便的操作(bushi),在c语言中,一个函数,只能有一种参数设置方法,或者说,一个函数一旦确定就只有一种用法,对同一组形参也只有一种结果。但 C嘎嘎有点特殊,c++允许在同一作用域中声明几个功能类似的同名函数,叫做函数重载,传入参数方法不同,结果也可能不同(通常用来处理功能类似数据类似的场景)。
这些同名函数的形参(个数 或 类型 或 顺序)必须不同
int add(int x, int y)
{
return x + y;
}
double add(double x, double y)
{
return x + y;
}
long add(long x, long y)
{
return x + y;
}
简单提一下,编译器经过优化在调试窗口观察难以说明,是由底层对不同的重载生成了不同的函数名称,从而实现了函数重载。
- extern c
使用extern ”c“即可在c++中使用c的风格来编译函数,也就是说,这块内容讲使用C语言方式编译,c++可以调用c,但c不可以调用c++
extern "c"
{
...
}
int main()
{
add(2,3)
}
引用
通俗来讲,引用就是取别名
int a = 0; //引用必须在定义时初始化
int &ra = a;
ra是a的别名,指向同一块空间
ra和a必须是同种类型
-
引用必须在定义时初始化
-
一个变量可以有多个引用
-
一个变量只能引用一个实体
常引用
在使用中,常引用比较常见,涉及到经过引用后权限的改变,一般的,经过引用,新别名的权限要小于等于被引用,否则会报错。
const int a = 10;//赋予了常属性,a的值不能更改
int& ra = a;//ra没有常属性,按语法是可以修改的,属于权限的放大,会报错
const int& ra = a;//√
int& b = 10 //b为常量,编译出错
const int& b = 20;//给予常性即可
类型不同的情况
double d = 3.14159;
int& rd = d;//编译出错,类型不同
const in& rd = d;//隐式类型转换中间产生临时变量,临时变量具有常性
两种使用场景
- 参数
void swap(int &a, int &b)
一般用于需要改变本身但传指针有缺陷的情况,涉及深浅拷贝。
- 返回值
int& addmax()
{
...
return n;
}
一般用于传类,减少拷贝次数
一般来说,传引用在时间和性能上效率较高
- 引用的底层时指针实现的
引用和指针的不同点 - 引用定义必须初始化,指针没有要求
- 引用只能对标一个实体,但指针可以反复横跳
- 没有空引用,但有空指针
- sizeof中,引用和引用类型有关,但指针只和地址所占空间大小有关
- ++引用使被引用+1,指针向后偏移一个类型
- 有多级指针,但没有多级引用
- 访问实体方式不同,引用编译器处理,指针显示解引用
- 引用较为安全
其他
内联函数
inline,一般函数短小精悍时可以使用内联函数。在调用是会直接在原地展开,省去了压栈等操作的开销,提升了运行效率,但这是一种空间换时间的做法。函数体较大或递归函数不适合使用。
inline int add(int x, int y)
{
return x + y;
}
int main()
{
int ret = add(1,2);//展开加优化
return 0;
}
-
注,inline会不会展开是一种建议,和编译器的优化有关
c++代替宏的方式
-
const常量定义
-
函数定义内联函数
宏的优点
*增加代码的复用性
*提高性能
宏的缺点 -
不方便调试
-
可读性差
-
没有类型安全的检查
auto关键字
auto关键字可以推到出声明变量的类型
也可以和指针与引用结合使用
- 使用auto定义变量必须进行初始化
- 一行声明多个变量时类型必须相同
- auto不能作为函数的参数
- auto不能直接声明数组
auto常用于范围for
是一种遍历方式
for(auto e : arr)
{
....;
}
e:用于迭代的变量(名称随意+
)
arr:迭代范围(指针,数组)//必须是确定的
- 同样可以用continue结束本次循环,也可以用break跳出整个循环
空指针
c++中,null是由宏定义的,是整形0
在c++中约定,表示空指针是最好使用nullptr
总结
接触类和对象的需要一些知识基础。(在c的基础上)