C++基础知识
Posted TangguTae
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++基础知识相关的知识,希望对你有一定的参考价值。
目录
从C转向C++
C是一种简单的语言。它真正提供的只有有宏、指针、结构、数组和函数。不管什么问题,C都靠宏、指针、结构、数组和函数来解决。而C++不是这样。宏、指针、结构、数组和函数当然还存在,此外还有私有和保护型成员、函数重载、缺省参数、构造和析构函数、自定义操作符、内联函数、引用、友元、模板、异常、名字空间,等等。用C++比用C具有更宽广的空间,因为设计时有更多的选择可以考虑。
出处:《Effective C++》
C++是一款面向对象的语言,面向对象的三大特性:封装、继承、多态。
封装可以使得代码模块化,继承可以扩展已存在的代码(类),多态使得接口的重用。
iostream
首先在C++里面不在是首先包含#include<stdio.h>,而是#include<iostream>,iostream是C++里面的输入输出流的库函数。
输出函数cout
std::cout<<"hello world"<<std::endl;
std是C++自己库里面的命名空间的空间名,cout代表输出函数,<<表示把需要输出的信息流向到cout里面,cout可以自动识别类型,而printf需要指定类型。
输入函数cin
std::cin>>i>>j;
cin是输入函数,把输入得到的值流向给i,j。
注意:cin遇到空格或者换行就会结束。
命名空间namespace
在命名空间中可以定义变量,函数,甚至是命名空间。
声明一个命名空间
namespace + 空间名 + 成员
namespace N1
int tmp;
int Add(int a, int b)
return a + b;
class sort
public:
void BubbleSort(int* const arr, int length);
;
namespace N2
int arr[10];
double d=3.14;
在命名空间外想使用命名空间里的变量、函数、类的三种方法:
1、加命名空间名称及作用域限定符
int main()
printf("%d\\n", N1::tmp);
return 0;
其中 :: 为作用域限定符,指定命名空间中的某个成员。
2、使用using将命名空间中成员引入
using N1::tmp;
int main()
printf("%d\\n", tmp);
return 0;
使用using 把 tmp 给展开,下面就可以直接调用。
3、使用using namespace 命名空间名称引入
using namespce N1;
int main()
printf("%d\\n", tmp);
Add(10, 20);
return 0;
缺省参数
缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。
void func(int a = 0)
std::cout << a << std::endl;
int main()
func();//输出默认值
func(10);//输出10
return 0;
全缺省
函数的参数都给一个缺省值
//全缺省
void func(int a = 0,int b=10,int c=20)
cout << a << endl;
cout << b << endl;
cout << c << endl;
int main()
func();//0,10,20
func(10);//10,10,20
func(10,20);//10,20,20
return 0;
半缺省
要求:从右往左缺省,必须按顺序;传参必须从左往右传参。
void func1(int a , int b = 10, int c = 20)//从右往左缺省
cout << a << endl;
cout << b << endl;
cout << c << endl;
int main()
func1();//错误的传参
func1(1);//从左往右传参
func1(1,20);//从左往右传参
func1(1,20,30);//从左往右传参
return 0;
函数重载
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。
注意:对返回值没有要求,如果只有返回值不同,不能构成重载,则报错。而且不包括缺省,缺省不算形参不同。
int add(int a,int b)
return a + b;
double add(double a, double b)
return a + b;
long add(long a, long b)
return a + b;
int add(int a)
return a + 10;
编译器自动识别参数类型
add(10,10);//默认调用第一个
add(10.0,10.0);//默认调用第二个
add(10L,10L);//用L标识他是长整型,去调用第三个
我们在linux环境下查看到底是如何实现函数重载的。
测试代码
main.c文件
#include<stdio.h>
int add(int a,int b)
return a+b;
int main()
return 0;
在linux下,把c代码文件转化成汇编语言。gcc -S mian.c,细节可以参考这篇文章
在汇编下,就是普通的函数名
在test.cpp文件中写入如下代码
#include<iostream>
int add(int a,int b)
return a+b;
double add(double a,double b)
return a+b;
int main()
return 0;
在命令行输入g++ -S test.c
在C语言环境下,编译出来的结果,在符号表里面他的函数地址映射后面的函数名没有发生变化,依然是原来的函数名所以无法生成多个相同的函数名,无法确定你要调用哪个函数。
而在C++下,函数名字的修饰发生改变。编译器将函数参数类型信息添加到修改后的名字中修饰后变成:_Z+函数长度+函数名+类型首字母。
所以说,为什么函数重载要求形参一定要不同,用来最后区分几个相同函数名的函数。
引用
一个很重要的C++里面的语法。
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
引用的特点
1、引用在定义时必须初始化
int a = 10;
int& aa ;
2、一个变量可以有多个引用
int a = 10;
int& aa = a;
int& aaa = aa;
a,aa,aaa共用同一个内存空间。
3、引用一旦引用一个实体,再不能引用其他实体
int a = 10;
int b = 20;
int& aa = a;
int&aa = b;//错误,引用多个实体
注意:引用类型必须和引用实体是同种类型的
有一个小的细节,除了类型以外,还有权限的问题。
当权限(读写)发生变化时,只能缩小权限,不能放大权限。
例如
const int a = 0;
int& aa = a;//错误的引用,因为权限放大了
int a = 0;
const int& aa =a;//权限发生变化,但是缩小不会报错
引用的作用
引用做参数或者引用做返回值,可以减少拷贝次数。
不过需要注意,做返回值时,不要返回临时变量。
指针和引用的区别
在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。
- 引用在定义时必须初始化,指针没有要求
- 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
- 没有NULL引用,但有NULL指针
- 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
- 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
- 有多级指针,但是没有多级引用
- 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
- 引用比指针使用起来相对更安全
内联函数
每次调用函数,会有一定消耗,即压栈等操作,如果频繁调度开销会很大。
C语言中使用宏函数来解决,C++用内联函数来解决。
内联函数是没有函数地址的
关键字inline
inline const int& add1(int a, int b)
return a + b;
inline关键字会在调用函数的地方把函数展开
内敛函数对于编译器而言只是一个建议,编译器会自动优化,如果内联函数里面的代码很多,编译器不会将它展开。
内敛的思想是用空间换时间。
注意:
内联函数体内不要有循环和递归。
以上是关于C++基础知识的主要内容,如果未能解决你的问题,请参考以下文章