本篇博客是对C++的一些简单知识分享,有需要借鉴即可。
C++简单入门目录
- 一、C++前言
- 1.C++的概念:
- 2.C++发展历程
- 3.C++如何学?
- 二、C++入门
- 1.C++关键字(C++98标准)
- 2.命名空间
- 3.C++输入&输出
- ①概念说明
- ②使用说明
- ③特征说明
- ④细节拓展
- ⑤cout与cin的意义
- 4.缺省参数
- ①概念说明
- ②使用规则
- ③应用举例
- ④缺省参数的意义
- 5.函数重载
- ①概念
- 6.引用
- ①概念
- ②特性
- 使用场景
- 1.做参数
一、C++前言
1.C++的概念:
一种高级编程语言,由C发展而来,满足过程化程序设计、基于对象的程序设计、面向对象的程序设计。
2.C++发展历程
C++最新发展:LINK
3.C++如何学?
- 写博客总结
- 定期画思维导图总结
- 常复习(博客笔记、知乎答案、看书)
- 刷题
二、C++入门
1.C++关键字(C++98标准)
2.命名空间
C++命名空间概念:一种命名域、是C++专门用来解决C语言变量命名冲突问题而产生的。
命名空间的意义:很大程度上解决C变量命名冲突问题。
知识拓展:C中的命名冲突
命名冲突主要有两大类:
程序员 与 库
程序员 与 程序员
知识拓展1:域,C++上指的是作用域LINK
在C++中,大体有四种域:
- 全局域:生命周期 访问
- 局部域:生命周期 访问
- 命名空间域:访问
- 类域
知识拓展2:编译器对名称的搜索原则:
- 在不指定域的情况下
- 当前域
- 全局域
- 在指定域的情况下
- 直接去指定域搜索
命名空间的定义: namespace关键字+命名空间的名字+{…}
- 命名空间中可以定义变量/函数/类型
- 命名空间可以嵌套
- 同一命名空间会被合并
namespace bit
{
// 命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
命名空间的使用:
- 法1:指定访问
需要用到访问操作符 ::
- 访问变量/函数 命名空间名称 + :: + 变量名/函数名
- 访问结构体 struct + 空间名 + :: + 结构体名
- 法2:直接访问(展开访问)
需要用到指令:using namespace + 空间名 —>等价于把空间内的命名放到全局变量
- 法3:展开特定项
eg:using std::cout;
总结:对比指定访问与展开访问,分析其利弊
答:
- 指定访问 解决变量冲突问题 麻烦
- 展开访问 直接把变量放到全局中 方便
- 部分展开 把常用的变量放到全局中 方便
其中,做项目一般使用第1与第3方式,第2种方法一般在练习中使用。
头文件展开与命名空间展开的区别:
头文件的展开本质是在预处理阶段拷贝头文件内容。
命名空间的展开本质是影响编译器的搜索规则。
3.C++输入&输出
①概念说明
cpp的输入输出分别是cout与cin,这两个函数均包含在iostream头文件中,在使用时需要展开命名空间进行使用。
②使用说明
#include<iostream>
using namespace std;
int main()
{
// <<,1.左移
int a = 10;
a = a << 1;
printf("a<<1:%d\n", a);
// <<,2.流插入
cout << "hello cpp" << endl;
// >>,1.右移
a = a >> 1;
printf("a>>1:%d\n", a);
// >>.2.流提取
cin >> a;
return 0;
}
③特征说明
下面是cout的特征说明示例:cin也是同理
④细节拓展
⑤cout与cin的意义
弥补了C语言自定义类型输入输出麻烦的问题
4.缺省参数
①概念说明
缺省参数是c++提供的一种在函数缺少传入值的情况下使用默认值的一种参数。
缺省参数分为两类
-
全缺省参数
-
半缺省参数
②使用规则
- 有实参优先使用,没有实参使用默认参数
- 缺省参数函数传实参时候从左到右依次给值,缺省参数函数形参从右向左依次给默认值
- 缺省参数不能在声明与定义中同时出现,要优先给函数声明使用缺省
- 缺省值必须是常量值或者全局变量
思考:为什么缺省参数要优先在函数声明中使用?而不是优先给函数定义使用?
答:
我们首先要明白编译器的编译原理,编译器首先要进行预处理,在这一步中展开头文件,之后编译器要进行编译,在这一步中编译器主要是检查语法,通常情况下,这种时候每个源文件都是独立的,每个调用函数的源文件中也自然大概率没有函数的定义,但是已经有了函数声明(因为经过了预处理),所以为了要让编译器不报错,肯定是先让函数声明有缺省参数。
那为什么不直接函数定义也有缺省参数,函数声明也有缺省参数呢?
因为语法是规定只能有一个的。
③应用举例
在c语言阶段,我们设计一个栈时候往往初始化不知道要给几个空间,这样我们可以给一个缺省参数来默认给值,然后不够了的话扩容。
④缺省参数的意义
对函数定义更加灵活化。
5.函数重载
①概念
函数名相同,函数参数不同,称为函数重载
函数参数不同在哪里?
- 参数的类型不同
- 参数的个数不同
- 参数的顺序不同
思考:编译器是如何支持函数重载的?C语言就不行。
答:名称修饰
6.引用
①概念
引用:底层汇编层面是用指针实现的,但是在语法层面上是为变量起别名,与指针起到互补作用。
②特性
-
引用在定义时必须初始化
-
引用不能更改指向
-
一个变量可以有多个引用
思考:引用可以完全替代指针吗?
答:不能,引用往往是在用指针比较复杂的地方代替指针。
为什么引用不能完全替代指针?
虽然引用可以在大多数情况下替代指针的使用从而简化指针,但是某些情况下是不能用引用解决的。
比如下面这个例子:
现在有一个单链表,要求删除中间的一个结点。
这里的关键点就在于引用不能改变指向,现在你把中间结点删除了,但是前面结点的指向怎么办?
//例子,链表
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType val;
struct SListNode* next;
}SLNode, * PSLNode;
//指针的方法
void SLPush(SLNode** pphead, SLTDataType x)
{
assert(pphead);
SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
newnode->next = NULL;
newnode->val = x;
if (*pphead == NULL)
{
*pphead = newnode;
return;
}
else
{
SLNode* pcur = *pphead;
while (pcur->next)
{
pcur = pcur->next;
}
pcur->next = newnode;
}
}
//引用的方法
void SLPush(SLNode*& pphead , SLTDataType x)
{
assert(pphead);
SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
newnode->next = NULL;
newnode->val = x;
if (pphead == NULL)
{
pphead = newnode;
return;
}
else
{
SLNode* pcur = pphead;
while (pcur->next)
{
pcur = pcur->next;
}
pcur->next = newnode;
}
}
void SLPrint(SLNode*& phead)
{
while (phead)
{
cout << phead->val << " ";
phead = phead->next;
}
}
void test_3()
{
SLNode* phead = NULL;
SLPush(&phead, 1);
SLPush(phead, 2);
SLPush(&phead, 3);
SLPush(phead, 4);
SLPrint(phead);
}
使用场景
1.做参数
void C_Swap(int* a,int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void CPP_Swap(int& a2, int& b2)//在这里可以起与实参一样的名字吗?可以。因为属于不同的域。
{
int temp = a;
a = b;
b = temp;
}
void test_1()
{
int a1 = 10;
int b1 = 20;
printf("a1 = %d , b1 = %d\n", a1, b1);
C_Swap(&a1,&b1);
printf("a1 = %d , b1 = %d\n", a1, b1);
int a2 = 10;
int b2 = 20;
cout << "a2 = " << a2 << " b2 = " << b2 << endl;
CPP_Swap(a2, b2);
cout << "a2 = " << a2 << " b2 = " << b2 << endl;
}
思考:在这里可以起与实参一样的名字吗?
答:可以,因为属于不同的域。
待续。