教材上不会和你讲的c++小知识

初识c++

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

随着数据结构和c语言的推进,现在已经进入了c++的学习进程中,现在,我们即将全面进入c++的学习


提示:以下是本篇文章正文内容,下面案例可供参考

一、命名空间

先看如下一段代码

#include<stdio.h>
#include<stdlib.h>
int rand = 0;

int main()
{
	printf("%d", rand);

	return 0;
}

这边报了一个这样的错误
在这里插入图片描述
那么为什么会出现这种情况呢,原因是rand在头文件stdlib.h中已被定义,在代码跑起来后,头文件展开,就会出现,rand重定义这个问题

这个c语言中的问题在c++中用了命名空间这个概念来解决

#include<stdio.h>
#include<stdlib.h>
namespace my
{
	int rand = 0;
}
int main()
{
	printf("%d", my::rand);

	return 0;
}

定义一个命名空间为my,包裹着我们所定义的内容

命名空间的定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

值得一提的是,命名空间内不止可以定义变量,函数,结构体等也都可以在其内定义

#include<stdio.h>
#include<stdlib.h>
namespace my
{
	int rand = 0;
	namespace my_
	{
		int p = 0;
	}
}

int main()
{
	printf("%d\n", my::rand);
	printf("%d\n", my::my_::p);
	return 0;
}

如以上代码,命名空间也是可以进行嵌套的,只是在使用时需要一层层剥开使用

注:编译器允许存在多个相同名字的命名空间,但在最后,会将其放在一个整的命名空间里,所以在相同命名空间里,变量名不可相同

命名空间的使用

(1)像我上面那样用::来使用
(2)可以指定某个变量

using N::b;
int main()
{
    printf("%d\n", N::a);
    printf("%d\n", b);
    return 0;    
}

(3)用using namespace + 命名空间来使用

std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中,所以很多时候都会使用using namespace std;

二、c++的输入和输出

#include<iostream>
using namespace std;
int main()
{
	cout << "hello c++" << endl;

}

(1)
cout是标准输出对象(控制台)
cin是标准输入对象(键盘)
使用它们两个是必须要包含头文件iostream和std标准库
(2)
<<是流插入运算符,>>是流提取运算符,我觉得这里的流用的很好,从键盘上流到电脑上为输入,从电脑上流到控制台上为输出
(3)
c++中是自动识别变量类型的
(4)
关于std标准库:在平时,我们可以直接用using来使用,在大型项目中,也可以不进行展开,用std::来代替

三、缺省参数

1、定义

在c语言中,在声明时有变量的函数,往往会忘记传参,这让我们很苦恼,在c++中,给了一个缺省函数的定义,来使我们使用函数时更加得心应手

void Func(int a = 0) {
 cout<<a<<endl; }
int main()
{
 Func();     // 没有传参时,使用参数的默认值
 Func(10);   // 传参时,使用指定的实参
return 0; }

如代码所示,缺省的含义就时在函数定义或者声明时(注:不能在声明和定义中同时存在,给变量赋予初始值,在传参时,如果有参数,则使用指定实参,若没有,则形参使用缺省值。

2、分类

缺省函数分为全缺省和半缺省,顾名思义就是形参的所给缺省值是否完全。值得一提的是,半缺省函数只能从右向左依次缺省

那么缺省值应该给什么值呢,能给常量吗?或者变量?答案是常量是肯定可以放的,但若想给变量,则需要给全局变量

四、函数重载

1、定义

c++允许出现函数名相同的函数存在,这些函数的形参不同(形参类型,位置等),用以处理不同需求的问题

#include<iostream>

using namespace std;
// 1、参数类型不同
int Add(int left, int right) {
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}
double Add(double left, double right) {
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}
// 2、参数个数不同
void f()
{
	cout << "f()" << endl;
}
void f(char b, int a) {
	cout << "f(char b, int a)" << endl;
}
int main()
{
	Add(10, 20);
	Add(10.1, 20.2);
	f();
	f(10, 'a');
	f('a', 10);
	return 0;
}

那么为什么c语言不能支持函数重载,而从c++能支持呢,c语言要粗糙一点,c++要细致一点,在符号表中,c语言会直接记录下函数名和函数地址,所以遇到重名函数会导致二义性,编译器无法区分调用哪个函数,但在c++中,函数名在符号表中根据函数的参数做了一些修改,具体修改方式就不细说了,大佬们想了解详情的可以去百度一下。

五、引用

1、定义

在学完c语言学习数据结构时,我们常常会看到书上给出这样的函数

void func(ST& p)

这里的&代表什么呢?这其实是c++中一个非常重要的概念:引用。
引用是已有变量的一个别名(所以引用一定要初始化),编译器不会给引用变量开辟空间,引用变量和被引用的公用一个空间。
在这里插入图片描述
这里要注意,既然是别名,那么定义时,需要与原变量类型相同。

2、性质

1、引用时必须初始化
2、一个变量可以有多个引用变量
3、引用变量不可以在改变自己的引用对象

3、关于常量的引用

	const int a = 10;
    //int& ra = a;   // 该语句编译时会出错,a为常量
    const int& ra = a;
    // int& b = 10; // 该语句编译时会出错,b为常量
    const int& b = 10;
    double d = 12.34

4、使用场景

1、作返回值
在这里插入图片描述
为何最后打印ret会是一个随机值呢?
我们上面说到,引用只是一个别名,那么在出Add函数时,c所在的内存被销毁,别名访问到的空间就是一个不被保护的,不确定的。
所以,在出函数作用域后,返回值变量会被销毁时,需要直接用传值返回

2、作参数
这是最常见的用法,我们在c语言中,需要改变变量时,往往会传变量的地址进去,在c++中使用引用后,就替代了传址。
在这里插入图片描述

5、传值和引用的效率区别

传值是开辟了一个临时变量(包括传值返回也是),而引用只是一个别名,甚至都不需要开辟多余的空间

6、引用和指针的区别

在语法概念上,引用只是变量的一个别名,公用一个空间,但在底层实现上,引用是利用指针的方式来实现的。

引用和指针的不同点:
1、引用只是概念上的定义一个空间的别名,而指针是开辟一个空间存放,然后指向一个变量的地址
2、引用必须初始化,指针不需要
3、引用初识化引用一个实体后,就不能在引用其他实体,而指针可以随意变换指向的对象
4、有空指针,但没有空引用
5、sizeof下,引用的大小为空间,指针的大小是地址空间占的字节数
6、引用自加为实体加一,指针自加是向后偏移一个类型的大小
7、有多级指针,但是引用只有一级
8、引用比指针更安全
9、指针的访问需要解引用

六、auto关键字

在实际代码中,总会遇到一些不容易写出类型名的变量,为了解决这一问题c++11赋予了auto新的含义

1、auto的使用

1、
在c++11后,auto不止用于存储类型指示符,更是作为了新的类型指示符来指示编译器,具体类型会在编译器使用时推导,要注意的是,在使用auto时必须要将变量进行初始化

2、auto和auto*是相同的,但在声明引用变量时,需要加上&,即为auto&;

3、在同一行声明多个变量时,这些变量需要是相同类型

auto a=0,b=1;
auto c=0,d=1.0;//会报错

2、auto不能使用的场景

1、不能作为函数的参数

int func(auto a);//会报错

2、不能声明数组

七、指针空值nullptr

在定义NULL这个宏时,给的是这样的定义

#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

可以看到,NULL可以被定义为0,也可以被定义为((void *)0),为了不引起误解,更多的使用代表((void *)0)的nullptr.

八、内联函数

1、定义

内联函数是一种用用inline修饰的函数,编译器在遇到调用内敛函数时会将其展开,以实现用空间换时间的效率提高。

#include<iostream>
using namespace std;

inline int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int ret = Add(1, 2);
	cout << ret << endl;
	return 0;
}

在这里插入图片描述

2、特性

1、内联函数在编译时会根据编译器的能力和进行选择性展开,如若我们在内联函数中使用了较多的语句,编译器就会忽视掉内联函数展开的请求。
2、被inline修饰的内联函数不会像普通函数一样进入符号表,所以内联函数声明和定义不能分开,否则会导致链接错误

总结

以上就是我们在正式学习c++重点知识前需要掌握的预备知识,尤其是引用,它有着传值和传址所不具有的一些优势,需要重点掌握。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值