【C++】入门知识

本文介绍了C++的基础知识,包括类的概念,变量的生命周期,命名空间的使用以解决命名冲突,以及内联函数和空指针等特性。重点讨论了函数重载和引用,阐述了它们如何提高编程效率和代码的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章是用作对C++的初步介绍,适用于入门,最好有C语言基础

介绍:

C++作为一门面对对象的热门语言,在经过几十年的发展依然在许多领域大放异彩,作为C语言的继承者,最重要的贡献就是提出类的概念,大大提高了开发人员的工作效率。

初步知识

首先要介绍的是域。
事实上在C语言里这个概念就已经有了。
域是由"{}"大括号所围成的空间,与域紧密相关的概念是变量的生命周期。
比如局部作用域,只要一个变量在这个域中创建,则这个变量的作用范围最多不会超过这个域,而且只要出了这个域,变量就会自动销毁。

    {
        static int a = 0;
    }

    printf("%d", a);//a为未定义标识符

命名冲突

在平时命名变量或者常量时,有一个问题的是命名冲突。一般有以下情况:
1、与库里的冲突
2、与项目中的冲突

要注意的是,在不同域中是可以重复命名的,但是在具体调用上是要遵循优先级顺序的。
具体是:局部域 -> 全局域 -> 展开了命名空间域 or 指定访问命名空间域

命名空间

我们可以自己创建一个空间,这实际上是命名空间域。在这个空间里:
1、我们可以根据实际需求来进行命名。
2、在这个空间可以保证一定的封闭性,就是在取用里面的成员时可以使用指定访问符 :: 来访问命名空间里的成员。

//namespace + 域名
{
	//具体内容
}
namespace test
{
    int a = 1;
}

printf("%d\n", test::a);//1

命名空间的展开:

使用代码:

using namespace + 域名;

事实上不推荐对命名空间进行展开
有好处:对于常用的库中已有的成员可以快速使用,不需要每次使用访问符来使用。

//std为标准库
std::cout << a << std::endl;
std::cout << a << std::endl;
std::cout << a << std::endl;
..........
//如果没有展开命名空间,需要重复这么写

但如果一个项目中的代码庞大,随意地展开就会发生命名冲突,这无疑造成更大的麻烦。

但是无需担心,C++是可以做到指定展开的

using 域名::需要使用的指令符
//ex:
using std::cout;
//这样之后对 cout 就无需再写std::

C++的输入和输出:

这个在前面的代码已经有出现输出符了。

运算符:

<<   //这个称为流输出运算符
>>   //这个称为流输入运算符
cout //表输出
cin  //表输入

“流”字可以很形象地描述程序的运行流程。

std::cout << a << " " << b << std::endl;
//从这个代码看,从cout后的第一个区域--a开始,其值被打印出来,然后是" " 和 b,最后是endl换行符

这就好像是从a开始,依次“流向”cout被打印出来。

便利性:

double a = 1.1;
//cout可以自动识别变量的类型,这其实使用了函数重载
std::cout << a << std::endl;//1.1

函数:

总体上和C语言的函数变化不是很大,不过多了很多新属性。

函数参数:

1、必须是从左到右提供参数,不能指定参数。
2、C++对应define在函数提供了一种供参方法——缺省参数,是从C语言的一大突破。
3、C++中的函数支持函数重载,但要注意,因为缺省参数的存在,函数可能会出现重载错误,需要额外注意。

缺省参数:

1、缺省参数是当提供的参数少于声明的参数个数时,函数会自动转换成带有默认参数值的新函数。
2、函数的声明和定义不能同时使用缺省参数,最好在声明处使用。
3、缺省参数相较于define来说更加灵活。

//函数声明
//其中b是缺省参数
int fun(int a, int b = 4);

int main()
{
	fun(1);//将会自动转换成 fun(1, 4);
	return 0;
}

int fun(int a, int b)
{
	cout << a << " " << b << endl;
}

函数重载:

1、在C语言中,对于同一个作用域而言,只要是同一个函数名,就不允许对返回类型、参数列表中的元素稍加改动。C++为了改变这个情况,决定引入函数重载。
2、在同一个作用域下,函数重载允许在同一个函数名的情况下通过对参数个数、参数类型、参数类型顺序的改动来实现函数重载。特别要注意的是,函数重载与返回值类型无关

int fun(int a, int b = 4);
//修改参数类型
int fun(char a, int b);
//修改参数个数
int fun(char a, int b, int c);
//修改参数类型顺序
int fun(int a, char b);

//必须要注意,在进行函数重构时,若已有的函数中有缺省参数,则要注意函数调用不明确
int fun(int a);
int fun(int a, int b = 4);

int main()
{
	//此时系统不知道要调用哪个参数
	fun(1);
	return 0;
}

为什么C语言不能实现函数重载而C++可以实现呢?
事实上这涉及到:
1、函数编译过程
2、函数名修饰规则

这部分比较复杂,感兴趣的话可以自行搜索理解背后原理。

引用:

引用很像C语言的指针,但这是对同一变量“取别名”,而这些别名可以是在不同空间下的对同一地址的不同表示形式
在实现和理解上比C语言的指针更容易。

//简单的实现:
int a = 0;
int& b = a;
//这个时候b就是a的别名,两者实质上指向的是同一个地址

//交换函数的革新:
void swap(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}

//若是对一级指针进行交换
void swap(int*& a, int*& b)
{
	int* temp = a;
	a = b;
	b = temp;
}

规则:

1、当一个变量确定作为引用后,其不能再引用其它变量

int a = 1;
int& b = a;
int c = 2;
b = c;
//这个时候为赋值,并且a和b的值都修改为c的值

2、一个变量可以有多个引用,这些引用就像是一个人的外号一般。

int a = 1;
int& b = a;
int& c = a;

3、引用在定义时就必须要初始化。

4、使用引用要将(表达式右边)权限大的传给权限小的一边(左边)。

使用场景:

作参数:

形参可以影响到实参

int fun(int& a , int& b)
{
	a = 1;
	b = 2;
}

这样就可以从函数内部修改到实参
不仅如此,这样传参对于一些“大型对象”有极高的效率

作返回值:

在C语言,每一次从函数返回之前都要先创建一个临时变量,这样是为了防止函数栈帧销毁后已经计算的数值无法传回去。
这并不是我们所想的返回值直接就传给用来接收的变量
如果使用引用,则会大大提高运行效率

//错误案例
int& fun(int x)
{
	return x;
}

//这里返回的是x的引用
//也就是说,其实这里存在的问题是可能出现随机值
//如果在传回引用时将函数栈帧销毁,那传回的引用的地址就指向随机值
int a = fun(11);
int& b = fun(12);

//正确案例
int& fun(int x)
{
	static int d = x + 2;
	return d;
}

常引用:

1、当将常量赋给引用时,必须将引用加上const来缩小权限范围

const int& a = 10;

2、如果是不同的数据类型,也必须要加上const

double a = 1.1;
const int& b = a;

引用与指针的区别:

1、引用不需要开空间而指针需要开空间。
2、从汇编来看,引用是类似指针来实现的。

内联函数:

C++中相较于C语言增添了一种新函数——内联函数。

//增加了一个关键字 inline
inline int fun(int x, int y)
{
	cout << x + y << endl;
}

内联函数与普通函数的区别:

内联函数在调用时不需要像普通函数一样先执行函数的执行体,再回调执行接下面的语句,而是类似宏函数一样,在调用处用内联函数体的代码来替换。

需要关注的地方:

1、inline 需要修饰在声明上。如果将声明和定义分开,有可能在会导致链接阶段失败。
事实上,inline函数不支持声明和定义分离开,因为编译器一旦将一个函数作为内联函数处理,就会在调用位置展开,即该函数是没有地址的,也不能在其他源文件中调用,故一般都是直接在源文件中定义内联函数的。

2、内联函数和宏函数类似,只是适用于短小没有递归的函数。因为关联函数不调用函数而是以函数体的代码直接在调用处进行替换,所以一旦遇上代码很长或者有递归亦或者是有循环的代码时,很可能会使得编译后的代码非常长。

3、为了避免以上情况的发生,一个函数是否是内联函数不是被inline修饰就行了,而是编译器在编译时看函数是否是以上情况自己作决定。

4、inline函数会在调用的地方展开,所以符号表中不会有inline函数的符号名,不存在链接冲突。可以在同一项目的不同源文件处写函数名相同的内联函数。

空指针:

在C语言中NULL是可以指空指针的,但在C++中,NULL是可以作为整形常量0,取而代之的是nullptr。
C++中的空指针:
1、sizeof(nullptr) 和sizeof((void*)0)所占的字节数一样。
2、nullptr在C++11是作为新关键字使用,不需要加入头文件才能使用。
3、为了不在一些场景中使用错误,在指向空指针推荐使用nullptr。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值