学习C++(一、预备知识)

一、预备知识

1、输入输出流:

cin >> 输入数据; //其中,cin为输入流类istream的对象,“>>”为提取运算符, 用于数据提取。
cout<< 输出数据; //其中,cout是输入流类ostream的对象,“<<”为插入运算符, 用于数据输出

2、名字空间:

using namespace std; //这是一句using编辑指令,表示可以在语句中使用cin cout endl等。
注:名字空间是由程序员设计并命名的一块内存区域,用于存放一些自定义的常量、变量、函数等标识符,从而与其他同名的标识符区分,避免冲突。
例:加入学校有5个叫张三的学生参加运动会,但是运动员检录时,无法通过名字区分5个张三,所以可以通过其他信息区分,假设5个人在不同班级,可以通过班级区分,如:3年级5班张三,3年级2班张三。
名字空间定义格式:
namespace 空间名 //namespace 是关键字 名空间是任意合法标识符
{
…; //声明或定义常量、变量、类、函数等。
}
如:
namespace space1
{
int a = 1;
void func1()
{
cout <<”function in space1 iscalled…”<<endl;
}
}
使用名字空间内定义或声明内容的方法:
(1)使用作用域运算符“::”限定标识符
space1::a;
count <<space1::a;
(2)使用using声明
using space1::a;
cout<<a;
(3)使用using编译指令
using namespace space1;
cout<<a;
注:在名称空间中的名称与局部名称发生冲突时,名称空间中的名称在局部名称范围内被隐藏。

3、数据类型

C++数据类型与C语言有着惊人的相似,当然由于这是两种不同的语言,所以也有少许区别,下面将介绍C++中与C语言不同的地方。
在C++中数据类型也分别为基本数据类型及构造类型。基本类型分为:整型、浮点型、布尔型、枚举类型等。在C++中有一个关于数据类型的名词为“宽度”,它表示存储数据时所占内存大小。
1、整型数据:
在整形数据中,按照宽度递增的顺序进行排序:short、int、long、longlomg;每种又分为有符号及无符号,所以整型数据共分为8中不同类型。
在C++中,并没有对整型数据的宽度做定义,不同的编译器规定的宽度不同,单基本原则如下:
(1)short 至少16位;
(2)int 至少和short一样长;
(3)long 至少32位是,且至少与int一样长;
(4)long long 至少64位,且至少与long一样长。
2、宽字符类型
在C/C++中,char都表示字符类型数据,通常char的宽度为1个字节(8位),最多可以表示(0~255)256个数据,但是在很多地方的字符长度超过256,如一个汉字占用2个字节,这是就需要用到宽字符类型数据。
(1)wchar_t类型
wchar_t:宽字符类型或双字节类型,一般为16位或32位,不同的C++语言库有不同规定。用‘L’前缀标识宽字符常量或宽字符字符串,在iostream中有相应针对wchar_t的操作,如:wcin/wcout 对宽字符类型数据进行输出或输入。
例:
wchar_t wch = L ’A’;
wcout<<wch<<endl;
(2)char16_t和char_32类型
char16_t:无符号长16位,C++11用前缀‘u’标识char16_t字符/字符串常量;如:u‘A’;u“hello”。
char32_t:无符号长32位,C++11用前缀‘U’标识char32_t字符/字符串常量;如:U‘A’;
U“hello”。
3、布尔(bool)类型数据
bool类型数据只有1、0表示真假(false、true)(在C语言中无bool类型数据,)
注:任何数字值或指针值可隐式的转换为bool类型值,规则是零值或空指针转为false,非零值和非空指针转换为true。
4、类型转换
(1)自动类型转换
(2)强制转换:
①格式1: (类型说明符) (表达式); //这也是c语言风格的强制转换
②格式2:类型说明符(表达式); //这是C++风格的强制转换
如: 格式1:(int)(x+y);
格式2: int(x+y);

注:强制格式转换并不会改变原有表达式的值,而是创建一个新的、指定类型的值。
(3)类型转换运算符:
①static_cast < 类型说明符> (表达式); //将表达式转换为< >中的类型说明符指定的类型。
②dynamic_cast <类型说明符> (表达式); //其中< >必须是类的指针、类的引用或void*。
③const_cast <类型说明符> (表达式);
④reinterpret_cast <类型说明符> (表达式); //
5、初始化列表
这是C++ 11推荐的一种使用大括号“{}”进行数据初始化的方法;
数据初始化的多种方法:
int n1 = 1;
int n2 (1);
int n3 = {1};
int n4{1};
注:列表初始化应用于基本数据类型时,不允许“缩窄”赋值,即用宽数据类型为窄数据类型变量赋值。

{//面试: const 与 #define 的比较 ,const有什么优点?
const    //const 常量 有数据类型,编译器可做类型安全检查

#define  //宏常量   没有数据类型,不做类型安全检查
         //只是进行字符替换 -> 替换可能会产生意料不到的错误
      
注意 //有些集成化的调试工具可以对 const 常量进行调试,但是不能对宏常量进行调试。
}

4、数组的替代方案

数组是一种构造类型,用于表示一组类型相同的数据,因为数组在使用时要注意下标不要越界,两个数组也不能通过数组名直接进行赋值操作,所以C++提供了向量vector和类模板array两种数组的替代方案。
(1)向量vector
vector可以看成是一个动态数组,用于存储一组类型相同的数据特点是:不定长、单向。(STL库)
头文件:#include
声明方法: vector <类型说明符> 对象名
vector <类型说明符> 对象名 (元素个数) //定义了元素个数n并不意味着仅能存储n个该类型数据,因为长度是不定的。
vector <类型说明符> 对象名 (元素初始值列表) //初始化成员列表,仍可再加
vector中元素引用方法:
<1>下标法 向量名[下标];
<2>使用成员函数 向量名.at[下标];

//vector
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector <int> nV{1,2,3,4,5,6};
    for(int i=0;i<5;i++)
    {
        cout << nV[i] <<" ";
    }
    cout <<endl;
    nV[2] = 0;
    nv.at(3) = -1;
    for()
}

(2)类模板array
类模板与普通数组一样也是定义一个定长的数组,它提供了丰富的成员函数可以实现特定功能。
格式:array <类型说明符,数组长度> 数组名;
头文件: #include

5、字符串 string

在C语言中,没有专门的字符串类型,string是C++的STL中一个字符串类
头文件: #include
名字空间: std
定义string字符串:
方法1:string s1;
方法2:string s2(“hello”);
方法3:string s3{“hello”};
方法4:string s4(5,‘a’); //声明字符串s4并且用5个‘a’初始化s4;
方法5:string s5(s2); //声明字符串s5,并用字符串s2初始化s5
(1)string的常用操作:
①数据输入输出
1)使用cin输入,但是不可包括:空格、回车、制表符等。
2)使用getline()函数输入
a.格式1:getline(cin,字符串,终止符); // 输入字符串,知道遇到终止符为止;
b.格式2:getline(cin,字符串); // 输入字符串,知道遇到“\n”为止;
3)输出:直接用cout << 即可。
②字符串连接:“+” (不必考虑内存大小)
1)s1 = s1+ s2; //将字符串s2连接到s1末尾,不用考虑s1的大小。
③字符串大小比较:使用成员函数compare()
1)s1.compare(s2); //比较s1及s2的大小,比较规则:从头开始比较ASCII的大小。
④访问string中某个元素:使用下标运算符“[ ]”,或成员函数:at( )

//例子:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
    //定义字符串的多种方法
    string s1;
    string s2("hello");     //等价于string s2 = "hello";
    string s3{"hello"};
    string s4(5,'a');
    string s5(s2);
    //string 常用操作
    cin >> s1;
    getline(cin,s1,'l');
    cout<< s1<<endl;
    getline(cin,s1);
    cout << s1 <<endl;
    s1.compare(s2);

}

6、指针与引用

C++中与C中类似。在定义指针时一般也会赋初值,避免出现野指针,导致程序异常。
(1)指针 : new 与delete
面向对象的程序编程,管理计算机内存空间(申请、释放)倾向于在运行阶段,而非编译阶段。
内存申请:new
格式1:类型说明符 * 指针变量名 = new 类型说明符;
在格式1中,用于申请一块内存空间,存储一个指定类型的数据:
//new delete
例:
int p = new int ; //申请一块可以存放int类型数据的空间,并经内存地址赋值给指针
//p,因为没有指定初始值,所以直接使用
p访问指针p指向的内 //存空间是没有任何意义的
//可以通过下面的方法申请内存空间并赋值
int *p = new int() ; //申请一块存储int类型数据的内存空间默认初始值为0;
int *p = new int(1) ; //申请一块存储int类型数据的内存空间默认初始值为1;
int *p = new int{1} ; //等价与int *p = new int(1)
格式2:类型说明符 * 指针变量 名= new 类型说明符[数组长度];
//格式2用于申请一块连续的内存空间,用于存储多个(用数组长度指定)指定类型的数据
例:
int *p = new int10; //申请一段连续的可存储10个int类型数据的空间,初始化为0

注:(1)用new申请数组时,( )中不能指定初始值,默认为0; { }内可以指定初始值;
(2)new申请的空间在堆区(Heap)或自动存储区(Free Store),而普通变量存储在栈区,区别在于,栈区数据会随着随着变量生命周期的结束自动回收内存,堆区则需要程序命令强制回收。

内存回收:delete
格式1: delete 指针名; //释放第一种申请格式申请的内存
格式2: delete[ ] 指针名; //释放第二种格式申请的内存

int *p;
*p = 1;     //错误,对于为未经赋值的指针直接修改其内存,是非法的。
int *q = NULL; //防止野指针出现
int *q1 = 1;
int *q2 = nullptr;      //nullptr等价于NULL

//new delete

int *p = new int ;      //申请一块可以存放int类型数据的空间,并经内存地址赋值给指针p,
                        //因为没有指定初始值,所以直接使用*p访问指针p指向的内存空间是没有任何意义的
//可以通过下面的方法申请内存空间并赋值
int *p = new int() ; //申请一块存储int类型数据的内存空间默认初始值为0;
int *p = new int(1) ; //申请一块存储int类型数据的内存空间默认初始值为1;
int *p = new int{1} ; //等价与int *p = new int(1)

int *p = new int[10]()//申请一段连续的可存储10个int类型数据的空间,初始化为0

(2)引用: 隐式指针。变量别名,指代同一实体(只读,声明时需初始化)->更安全、可读性维护性更好
引用与指针区别:引用是变量别名,指代实体本身;指针则是指代实体线索。指针是一种(构造)数据类型,引用不是,所以编译器不会给引用分配存储单元。
分类: 左值引用;右值引用
<1>左值引用(左值是可以放在赋值号左侧的对象)
格式:类型说明符 &引用名 = 目标变量;
例: int a ,b,c=1;
int & ra = a;
int & ba; //非法,因为引用声明时必须初始化
int & ra = b; //非法,因为ra 已经是变量a的引用(别名),不可以用作其 他变量别名。
double & ca = c; // 语法错误,引用不能进行数据类型转换,必须与目 标变量类型一致 ;
int & ca = 1; //左值引用不能绑定常量;

用const 限制左值引用:const 类型说明符 & 引用名 = 目标变量名;
//带const 的引用 也称为“常引用”

//利用引用进行数据交换
#include<iostream>
using namespace std;

int swap(int &a, int &b)
{
    int c;
    c = a;
    a = b;
    b = c;
}

int main()
{
    int i = 1;
    int j = 2;
    cout<< "i="<<i<<",j="<<j<<endl;
    swap(i,j);
    cout<< "i="<<i<<",j="<<j<<endl;
}```

## 7、函数重载

重载(静态绑定即编译期绑定):同名不同参,智能匹配 -> 参数类型可变或参数个数不同
例://函数重载

```cpp
#include <iostream>
#include <string>
using namespace std;

int add(int x,int y)
{
    return x+y;
}
int add(int x,int y,int z)
{
    return x+y+z;
}

double add(double x,double y)
{
    return x+y;
}
string add(const string s1,const string s2)
{
    return s1+s2;
}

int main()
{
    cout << add(1,2) << endl;
    cout << add(1,2,3) << endl;
    cout << add(1.3,2.2) << endl;
    cout << add("hello ","world") << endl;

}

注:
<1>不能用函数返回值的类型区别两个重载函数;
<2>形参的名字不能用于区别两个同名函数;
<3>普通变量与其引用具有相同的特征标;(形参不能采用普通变量及引用进行区分)
<4>函数形参可以使用const 进行区分两个重载的函数;
<5>函数重载只发生在同一作用域内的同名函数间,不同作用域的同名函数不会发生重载。

8、默认参数

在函数重载中,因为多个重载函数之间可能拥有大量重复代码,只是因为参数个数不同,就需要重复大量工作,所以出现了默认参数,减少代码量。
例:

#include <iostream>
#include <string>
using namespace std;

int add(int a,int b,int c = 0,int d = 0); //有函数声明时,默认参数只能在声明中指定
int main()
{
    int a = 1,b = 2,c = 3,d = 4;
    cout << add(a,b)<<endl;
    cout << add(a,b,c)<<endl;
    cout << add(a,b,c,d)<<endl;
    return 0;
}

int add(int a,int b,int c,int d)
{
    return a+b+c+d;
}

注:
<1> 如果有函数声明,则默认参数只能在函数声明中指定;没有函数声明,则可以在函数定义中指定;
<2>默认参数的顺序是自左向右的,如果某个参数指定为默认值,则它右边的所有参数都必须设置为默认值;
<3>默认值可以是全局变量、常量、函数等,但是不可以是局部变量,因为在编译阶段就需要确认默认值,但是局部变量编译时无法确定;
<4>避免默认参数与函数重载的二义性。

9、内联函数

内联函数与普通函数的区别: 普通函数,在程序执行到函数调用时,是跳转到被调函数处,并记录跳转地址,执行完再跳转回原来位置;内联函数则是将调用函数直接复制到函数调用处,不用记录跳转地址,也不用来回跳转,所以常用在调用函数代码少、执行速度快、需要频繁调用的地方。省时但浪费内存。
格式:只需要在函数定义及声明是加上关键字:inline

//内联函数
inline int add(int x,int y);
inline int add(int x,int y)
{
return x+y;
}```

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值