初识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++重点知识前需要掌握的预备知识,尤其是引用,它有着传值和传址所不具有的一些优势,需要重点掌握。