数据类型
数据类型 | 类型说明符 | 位数 | 取值范围 |
整型 | int | 32 | -2147483648~+2147483647 |
短整型 | short int | 16 | -32767~+32768 |
长整型 | long int | 32 | -2147483648~+2147483647 |
单精度浮点型 | float | 32 | -3.4E-38~+3.4E+38 |
双精度浮点型 | double | 64 | 1.7E-308~1.7E308 |
字符型 | char | 8 | -128~+127 |
cout
cout <<fixed fixed 强制以小数形式显示,现实所有小数
cout<<setprecision(2) 控制显示的精度 2代表两位小数 头文件 <iomanip>
cout<<setw(8) 设定宽度 只管后面一个数字
cout<<setfill('_') 设定下划线填充
cout<<left 左对齐
cout<<boolalpha 打印true false
getchar() cin.get()
SetConsoleTile(""); 更改cmd的名字
/** */ 文档注释
位运算
算术运算符优先级
! ~ ++ -- sizeof
!
算数运算符
关系运算符
&&
||
赋值运算符
单目运算符 包括!~ ++ -- sizeof,优先级别高
赋值运算符优先级别最低
()优先级最高
从右向左结合性的只有赋值运算符、三目运算符和单目运算符
算术运算符 > 关系运算符 > 逻辑运算符
switch注意:
switch后的表达式只能是整型或字符型
case后常量表达式的值不能相同
case后允许多条语句,不需要大括号
如果不添加break语句,需要特别注意执行顺序
case和default子句的先后顺序可以自行变动
default子句可以省略
sizeof()特例 不执行num++
#include <iostream>
using namespace std;
int main()
{
int num=5;
cout << sizeof(num++)<<endl;
cout << num << endl;
return 0;
}
输出:4 5
数组和指针
数组名就是这块连续内存单元的首地址
int num[5];//num是数组名,也可以理解成数组的首地址
num的值与&num[0]的值是相同的
数组第i+1个元素可表示为:
第i+1个元素的地址:&num[i+1]或num+i
第i+1个元素的值:num[i+1]或*(num+i+1)同样尝试*++ptr_num
为指向数组的指针赋值:
int*ptr_num = num;或int *ptr_num =&num[0];
指针变量可以指向数组元素
int *ptr_num = &num[4]或int*ptr_num = num+4;
vector常用函数
常用操作 |
clear() | 移除容器中的所有数据 |
empty() | 判断容器是否为空 |
size() | 返回容器中元素的个数 |
[index]、at(index) | 返回索引为index的元素 |
erase(pos) | 删除pos位置处的数据 |
erase(beg,end) | 删除[beg,end)区间的数据 |
front() | 返回第一个元素 |
insert(pos,elem) | 在pos位置处插入一个元素 |
pop_back() | 删除最后一个元素 |
push_back(elem) | 在容器末尾插入一个元素 |
resizer(num) | 重新设置容器大小 |
begin()、end() | 返回容器首尾元素的迭代器 |
https://blog.csdn.net/weixin_41743247/article/details/90635931
#include<algorithm>
//对a中的从a.begin()(包括它)到a.end()(不包括它)的元素进行从小到大排列
sort(a.begin(),a.end());
//对a中的从a.begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素为1,3,2,4,倒置后为4,2,3,1
reverse(a.begin(),a.end());
//把a中的从a.begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开始复制,覆盖掉原有元素
copy(a.begin(),a.end(),b.begin()+1);
//在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置
find(a.begin(),a.end(),10);
#include<vector>
vector<int> a,b;
//b为向量,将b的0-2个元素赋值给向量a
a.assign(b.begin(),b.begin()+3);
//a含有4个值为2的元素
a.assign(4,2);
//返回a的最后一个元素
a.back();
//返回a的第一个元素
a.front();
//返回a的第i元素,当且仅当a存在
a[i];
//清空a中的元素
a.clear();
//判断a是否为空,空则返回true,非空则返回false
a.empty();
//删除a向量的最后一个元素
a.pop_back();
//删除a中第一个(从第0个算起)到第二个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+3(不包括它)结束
a.erase(a.begin()+1,a.begin()+3);
//在a的最后一个向量后插入一个元素,其值为5
a.push_back(5);
//在a的第一个元素(从第0个算起)位置插入数值5,
a.insert(a.begin()+1,5);
//在a的第一个元素(从第0个算起)位置插入3个数,其值都为5
a.insert(a.begin()+1,3,5);
//b为数组,在a的第一个元素(从第0个元素算起)的位置插入b的第三个元素到第5个元素(不包括b+6)
a.insert(a.begin()+1,b+3,b+6);
//返回a中元素的个数
a.size();
//返回a在内存中总共可以容纳的元素个数
a.capacity();
//将a的现有元素个数调整至10个,多则删,少则补,其值随机
a.resize(10);
//将a的现有元素个数调整至10个,多则删,少则补,其值为2
a.resize(10,2);
//将a的容量扩充至100,
a.reserve(100);
//b为向量,将a中的元素和b中的元素整体交换
a.swap(b);
//b为向量,向量的比较操作还有 != >= > <= <
a==b;
指针 char*
char ch = 'a';
char *ptr_ch = &ch;
cout<< (void *)ptr_ch<<endl;
在c语言中char *是默认当成字符串 输出ptr_ch会当作字符串输出,但是没有'\0'结束符会打印别的不知道什么东西,强制转换成(void *)说明是指字符指针就可以打印地址了
char ch = 'z';
char *ptr_ch = (char*) malloc(1 * sizeof(char));
*ptr_ch = ch;
//*(ptr_ch+1) = '\0';
cout<< ptr_ch<<" "<<*ptr_ch<<endl;
return 0;
int *ptr1 = nullptr; //等价于int *ptr1=0;
int*ptr2 = 0; //直接将ptr2初始化为字面常量0
引用
引用对指针进行了简单封装,底层仍然是指针
获取引用地址时,编译器会进行内部转换
引用的本质在c++内部实现是一个指针常量
//发现是引用,转换为 int* const ref = &a;
void func(int& ref){
ref = 100; // ref是引用,转换为*ref = 100
}
int main(){
int a = 10;
//自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改
int& ref = a;
ref = 20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;
cout << "a:" << a << endl;
cout << "ref:" << ref << endl;
func(a);
return 0;
}
地址占四个字节,指针就是占四个字节
常量引用
常量引用主要用了修饰形参,防止误操作
//引用使用的场景,通常用来修饰形参
void showValue(const int& v) {
//v += 10;
cout << v << endl;
}
int main() {
//int& ref = 10; 引用本身需要一个合法的内存空间,因此这行错误
//加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;
const int& ref = 10;
//ref = 100; //加入const后不可以修改变量
cout << ref << endl;
//函数中利用常量引用防止误操作修改实参
int a = 10;
showValue(a);
system("pause");
return 0;
}
c++函数
内置函数 Boost C++
C++中返回值类型不能是数组,但可以是其他任何类型(可以将数组作为结构或对象组成部分返回)
注意:1、数组作为函数实参时,只传递数组的地址(首地址),并不传递整个数组的空间 2、当用数组名作为实参调用函数时,数组首地址指针就被传递到函数中
void show(double (*)[5],int);
int main()
{
double powers[3][5] = {
{45.5,55.6,88.9,66.6,78},
{98.2,60.1,33.7,49.3,59},
{78.2,58.5,12.8,37.8,43}
}
show(powers,3);
return 0;
}
void show(double (*arr)[5],int len)
{
for(int i=0;i<len;i++){
for(int j=0;j<4;j++){
cout<<*(*(arr+i)+j)<<",";
}
cout<<endl;
}
}
也可以是 void show(double [][5],int len);
void show(double arr[][5],int len){...}
函数默认参数
int func(int a, int b = 10, int c = 10) {
return a + b + c;
}
//1. 如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值
//2. 如果函数声明有默认值,函数实现的时候就不能有默认参数
int func2(int a = 10, int b = 10);
int func2(int a, int b) {
return a + b;
}
int main() {
cout << "ret = " << func(20, 20) << endl;
cout << "ret = " << func(100) << endl;
system("pause");
return 0;
}
函数占位参数
C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置
//函数占位参数 ,占位参数也可以有默认参数
void func(int a, int) {
cout << "this is func" << endl;
}
int main() {
func(10,10); //占位参数必须填补
system("pause");
return 0;
}
函数指针
函数也有地址
函数的地址是存储其及机器语言代码的内存开始地址
可以在不同的时间使用不同的函数
//函数原型:
double sum(double,double);
//函数指针声明:
double(*ptrSum)(double,double)
注意:
1、该语句声明了一个指针ptrSum,指向一个函数
2、double *ptrSum(double,double) 不是函数指针,而是声明了一个函数ptrSum,返回double*类型
重点:
1、c++11中可以使用auto ptrFunc=addition;自动推断类型(自动类型推断需要确保变量的类型与初值类型一致)
2、可以使用typedef简化声明:
typedef double (*ptrCalc)(double,double);
ptrCalc ptrFunc;
内联函数 inline
内联函数 是c++为提高程序运行速度所做的一项改进
与常规函数的区别不在于编写方式,而在于被调用时的运行机制不同
使用建议:
如果执行函数代码的时间比处理函数调用机制的时间长,则节省的时间将只占整个过程的很小一部分;如果代码执行时间很短,内联调用就可以节省大部分时间
内联的使用(二选一)
在函数声明前加关键字inline
在函数定义前加关键字inline
引用做参数和返回值
注意:
1、引用并非对象,只是为一个已经存在的对象起的别名
2、引用更接近const指针,一旦与某个变量关联起来,就将一致效忠于它
3、将引用变量用做参数时,函数将使用原始数据,而非副本
4、当数据所占内存比较大时,建议使用引用参数
函数返回引用类型
1、不要返回局部变量的引用
2、函数可以不返回值,默认返回传入的引用对象本身
3、返回引用时,要求函数参数中包含被返回的引用对象
int & sum(int &num)
{
num++;
return num;
}
int main()
{
int num=10;
int &result = sum(num);
sum(num)=55;
cout <<"result="<<result<<endl;
return 0;
}
输出为:55
使用引用参数的一些指导规则
1、能够修改调用函数中的数据对象
2、数据对象较大时传递引用可以提高程序的运行效率
函数中不需要修改传递的参数
如果数据对象很小,建议按值传递
传递数组只能使用指针,并使用const关键字
较大的对象则使用const指针或引用,以提高程序的效率
函数中需要修改传递的参数
数据对象是基本类型或结构时,可以使用指针或引用(基本类型建议使用指针)
数据对象是数组时只能使用指针
数据对象是类对象时,要求使用引用
默认参数
函数重载
同一个作用域下 ,函数名相同,参数列表不同 类型不同或者个数不同或者顺序不同
函数返回值不可以作为函数重载的条件
特征标 重载-编译器在编译时,根据参数列表对函数进行重命名(void Swap(int a, int b) Swap int int)
编译器把类型引用和类型本身视为同一个特征标
const能不能区分重载要看参数是值传递还是引用传递
int test(int &i)
{
cout<<"test01 "<<i<<endl;
return i;
}
int test( const int &i)
{
cout<<"test02 "<<i<<endl;
return i;
}
上面的test函数是重载的,如果没有使用引用或者指针,会报错 函数重定义。
模板函数
函数模本就是建立一个通用函数:
函数定义时不指定具体的数据类型(使用虚拟类型代替)
函数被调用时编译器根据实参反推数据类型-类型的参数化
//模板头与函数声明/定义永远是不可分割的整体
template <typename 类型参数1,typename 类型参数2,...>
返回值类型 函数名(形参列表){
//在函数体中可以使用类型参数
}
//函数声明
typename<typename T> void Swap(T&,T&);
/**
*使用模板技术实现变量交换值
*/
template<typename T>//模板头与函数声明/定义永远是不可分割的整体
void Swap(T &a,T &B)
{
T temp = a;
a=b;
b=temp;
}
类和对象
1、class方式声明的类型与struct声明的类型仅仅是形式上不同。
2、其唯一的区别在于使用class声明的类型默认成员是私有的(private),而struct声明的类型默认成员是公有的(public)
访问权限有三种:
1. public 公共权限
2. protected 保护权限
3. private 私有权限
示例:
//三种权限
//公共权限 public 类内可以访问 类外可以访问
//保护权限 protected 类内可以访问 类外不可以访问
//私有权限 private 类内可以访问 类外不可以访问
构造函数
以类名作为函数名
无返回值类型
作用
初始化对象的数据成员
类对象被创建时,编译器为对象分配内存空间并自动调用构造函数以完成成员的初始化
构造函数的种类
无参构造
一般构造(重载构造)
拷贝构造
注意:
1、如果创建的类中没有写任何构造函数,系统会自动生成默认的无参构造函数(函数为空,什么都不做)
2、如果书写了构造函数,系统就不会再自动生成默认构造;如果希望有一个这样的无参构造函数,需要自己显示的书写出来
带参构造
类名::构造(类型1 参数1,类型2 参数2,...){
//代码
}
Student::Student(string name,string desc){
_name = name;
_desc=desc;
}
构造函数重载 和普通函数重载相同
Student();
Student(int);
Student(string,string);
//初始化参数列表
Student::Student(string name,string desc):m_Name(name),m_desc(desc){}
析构函数
析构函数
当对象过期时自动调用的特殊成员函数
析构函数一般用来完成清理工作
析构函数的名称是在类名前加上~
析构函数没有参数,只能有一个
注意:
析构函数用来释放对象使用的资源,并销毁对象的非static数据成员
无论何时一个对象被销毁,都会自动调用其析构函数(隐式析构)
class Student{
private:
double *scores;
public:
Student(int len)
{
//使用new
scores = new double[len];
}
~Student()
{
delete scores;//释放资源
}
}
析构函数 不能释放 堆 要用delete
实例化
this指针
每个成员函数(包括构造和析构)都有一个this指针
this指针指向调用对象,即可以通过this关键字访问当前对象的成员
访问成员变量 this->成员名;
访问成员函数 this->函数名()
注意:
1、this指针的类型为类类型*const(类名*const),为右值
2、this指针本身不占用大小,它不是对象的一部分,因此不会影响sizeof的结果
3、this的作用域在类成员函数的内部
4、this指针是类成员函数的第一个默认隐含参数,编译器自动维护传递,类编写者不能显示传递
5、只有在类的非静态成员函数中才可以使用this指针,其他任何函数都不可以
函数最后加const 说明不能修改this
Student &GetSuperScolar(Student&) const;
//函数的结尾声明为const;函数内部不允许修改对象本身,调用本对象非const方法就会报错
this返回对象指针
运算符重载 operator
运算符重载格式
返回类型 operator被重载的运算符(参数列表)
class Integer
{
public:
Integer():m_num(0){}
Integer(int num):m_num(num){}
const Integer operator+(const Integer &other)const{
cout<<"重载运算符+,一遍实现两个整型对象相加"<<endl;
return Integer(this->m_num+other.m_num);
}
private:
int m_num;
}
Integer num1(1024);
Integer num2(2048);
Iteger num3 =num1 + num2;
//实际调用
//num3 = num1.operator+(num2);
const
const 修饰变量
1、只有一个const时,如果const位于*的左侧,表示指针所指的数据是常量,不能通过该指针修改实际数据;指针本身是变量,可以指向其他内存单元
2、只有一个const时,如果const位于*的右侧,表示指针本身是个常量,不能指向其他内存单元;所指向的数据可以修改
3、如果有两个const位于*左右两侧,表示指针和指针所指向的数据都不能修改
const成员函数不能调用非const成员函数
const修饰引用时,不能修改引用对象的任何成员,好处是可以保护传递参数,不需要一个新的参数副本
Integer num1(1024),Integer num2(24);
Integer num3 = num1+num2;//正常执行
Integer num4 = 1024 +num1;//编译错误
Integer Integer::operator+(const Integer &other);
是作为成员函数重载的, num1.operator+(num2)合法
但是1024.operator+(num1)中,int类型并没有重载+号
使用友元函数
friend const Integer operator+(const Integer&,const Integer &);
friend ostream &operator <<(ostream &,const Integer &);
const Integer operator+(const Integer &leftNum,const Integer & rightNum){
return Integer(leftNum.m_num + rightNum.m_num);
}
ostream &operator<<(ostream &out,const Integer &num){
out <<num.m_num;
return out;
}
运算符声明成类成员还是声明独立友元函数建议准则:
C++规定,复制运算符=、数组下标运算符[]、函数调用运算符()、成员访问运算符->在重载时必须声明为类的成员函数
流运算符<<、>>、类型转换运算符不能定义为类的成员函数,只能是友元函数
一元运算符和复合复制运算符重载时,一般声明类的成员函数
二元运算符在运算符重载时,一般声明为友元函数
注意:
1、对于很多运算符来说,可以选择使用成员函数或非成员函数来实现运算符重载,一般来说,非成员函数应该是友元函数,这样才能直接访问类的私有数据
2、在定义运算符是,必须选择其中的一种格式,而不能同时选择这两种格式,同时定义这两种格式将被视为二义性错误,导致编译错误
3、那么哪种格式最好呢?对于某些运算符来说,成员函数时唯一合法的解释。在其他情况下,这两种格式没有太大的区别。有时,根据类的设计,使用非成员函数版本可能更好(尤其是为类定义类型转换时)
//流运算符 一般只能使用友元的方式重载
friend ostream &operator<<(ostream &out,const Integer &num);
ostream &operator<<(ostream &out,const Integer &num)
{
out << num.m_mvalue;
return out;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)