文章目录
1. 基础
1.1
- C++区分大小写,拓展名为cpp
- C++头文件扩展名没有扩展名,有些C的头文件转化为C++头文件,去掉h头文加上前缀c(math.h->cmath)
main函数
-
C++的标准主函数形式
int main() { } -
C语言标准主函数
int main(void) { } -
c++标准
# include <iostream> using namespace std;
2.常量
作用:记录不可更改的数据
- #define 宏定义:
#define 常量名 常量值 #define week 7 - const 修饰的变量
- const作用是保护被定义的值不被改变。
const 数据类型 常量名=常量值 const int week=7; // 是week的值一直为7 week=2; //就会报错
3.关键字
sizeof关键子
- 作用:统计数据类型所占内存大小
- 语法:sizeof(数据类型或者变量名)
cout << "long型所占内存大小:"<< sizeof(long) << endl;
endl
- 作用:换行
- endl:屏幕光标移到下一行开头,重启一行,刷新缓冲区
- /n:重启一行
C++同时支持两种换行方式
字符串
两种字符类型
- C++ 有两种风格的字符串
- 字符串都要放在""中
- C语言风格的字符串
char 变量名[]=“字符串值”
char cat[8]={'a','s','f','/0'} ; //如果逐个字符的赋值,最后一定要加上/0(空字符)
//更为简单的方法
char bied[11] = "MY right"; //直接双引号一个字符串,不需大括号。
cin >> bied ; //字符串的输出
- C++ 风格的字符串
string 变量名=“字符串”
- 要用string型的字符串要添加一个#include< string >的头文件
string类的操作
-
string类可以通过+运算符,把两个字符串来接起来。
-
不能将一个字符数组赋给另一个字符数组,但是string可以
-
使用函数
strcpy()可将字符串复制到另一个数组中,原数组会被覆盖掉
strcpy(charr1,charr2);//把charr2复制给charr1 -
使用函数
strcat()可将字符串添加到另一个数组后面
strcat_s(a1, a2); -
strcat()可能会因为数据的申请空间不够,而导致覆盖相邻内存,导致程序终止。但string类具有自动调节大小的功能。
-
length(),strlen(),size(),sizeof()
-
length()只是用来计算字符串中申请内存空间的长度。
-
size()函数与length()函数作用相同,在C++中。
-
sizeof()运算符用来求对象申请内存空间的大小(char a[20] 表示申请了20个字符空间)
-
strlen()用来计算字符串的长度(不包括空字符),储存数据的长度,参数为字符指针
char a1[20] = "abcd";
string a2 = "qwer";
int b1=strlen(a1); // b1 = 4
int b2=size(a1) ; // b2 = 20
int b3=sizeof(a1); // b3 = 20
int c1 = strlen(a2.c_str()); //c1 = 4
int c2 = size(a2); //c2 = 4
int c3 = sizeof(a2); //c3 = 28
4.输入输出
4.1 命名空间
有输入输出的函数需要加上using namespace std;命名空间,就可以直接使用cin,cout不用加上std::的前缀。
4.2 输入cin
语法:cin >> 变量名
int a = 0;
cin >> a;
floar f;
cin >> f;
char ch;
cin >> ch;
string str = "hello" ;
cin >> str ;
int c ;
double d ;
cin >> c >> d; // 连续命名
- 当给布尔类型赋值
bool flag = false;
cin >> flag;
只要赋值不是0,bool类型的值都是真
4.3 输出cout
- 语法
cout <<" "; - 连续输出
cout <<内容<<内容<<内容;
cout <<"hello word"; //输出字符串
cout << 12.12; //输出数字
cout<<'d'; //输出字符
cout << "hello word"<<12.12 << 'd'; // 连续输出
4.4 面向行输入getline()
geline()函数读取整行,通过回车键换行来确定结尾,会读走并删除换行符
- getline函数有两个参数,1.数组名,2.参数要读取的字符数(个数包括换行符)
cin.getline(name,20);
- geline函数每行通过换行符结尾,但是不保存换行符,并用空格替换,由于空格站一位,所以参数是20,最多读取19个字符。
4.5 面向行输入get()
iostream类的另一个函数,工作方式与getline类似,连个参数,但是get函数将换行符留在输入的队列中。
cin.get(name,20)
- 由于get函数将换行符留在输入的队列中,当两连续的
cin.get(name,size)同时出现时,由于第一个输入行的结尾保存的换行符,是的第二个输入结束输入,所以第二个输入,无法有效运行,可以用cin.get()来读取第一个中的换行符。
cin.get(name, ArSize);
cin.get(desert, ArSize);
解决后:
cin.get(name, ArSize);
cin.get();
cin.get(desert, ArSize);
// 另一种使用方法是将连个合并
cin.get(name, ArSize).get(); // 效果相同
cin.get()该函数只能读取一个字符。cin.getline()也能读取换行符,但是使用get()的比较多- 当输入的字符大于费分配的空间长度,get()与getline()将把多余的字符留在输入队列中,getline()还会设置失效位,并关闭后面的输入。
5.命名空间 namespace
- 作用: 区别相同的变量和函数
- 放在main函数外
- 定义格式:
namespace 空间名 { }// 最后这里有无;都可以 - 调用格式
空间名::空间中的函数(变量)名;
当一个程序中有两个相同的变量、函数或其他的什么,可以定义两个不同的命名空间,不两个相同的变量分别放在两个命名空间里
namespace pace1
{
void sort()
{
}
}
namespace pace2 //定义
{
void sort()
{
}
}
pace1::sort(); //调用
pace2::sort(); //调用
6.结构体
- 与C语言结构体大致相同,细节上有些区别
- 声明变量可以不用struct关键字
#include <iostream>
using namespace std;
struct node // 定义一个node类型的结构体
{
int m;
}
int main()
{
node a; // 定义了一个node类型结构体,结构体名字为a.
struct node a; //C语言需要用在node前要加一个struct关键字
}
- C++可以再结构体里面放函数,C不可以,不过C可以放函数地址
struct node // 定义一个node类型的结构体
{
int m;
void fun() //C++允许在结构体里面放函数
{
cout<<"hahaha";
}
}
7. new和delete
- new 空间申请,类似于malloc
- delete 空间释放,类似于free
单个空间的申请
int *p=(int*)malloc(sizeof(int)); //C语言的malloc申请款空间
int *p1=new int; // C++的new申请款空间 //new type,type的类型一定要与定义的匹配
delete p1; //删除空间 直接把想要删除的地址写上
int *p2 = new int(121); //空间申请的时候可以直接初始化
int *p2 = new int;
*p2 = 121; //也可以分布赋值
数组空间的申请
int *p = malloc (4*5); //C语言的malloc申请款数组空间
int *p2 = new int[5] ; //C++的new申请款空间
delete [] p2; //数组释放的时候要加[]
- 由于C++没有在给数组申请空间的初始化,可以用 memset
memset
可以为各种类型的新申请的空间进行初始化.
- 由于她是直接为内存进行操作,所以memset可对一些数据量很大的结构体,数组赋值速度很快
int stu[10];
int *p=stu;
memset(stu,1,sizeof(stu)); // stu数组中的是就都会被赋值为1。
指针空间的申请
int* ps = new int;
delete ps;
int* psome = new int [10];
delete [] psome ; // 释放数组指针空间的时候一定要加[],表示要释放整个数组,而不是指针指向的元素。
注意
- 单个元素的释放是delete p,数组空间的释放是delete [] p,一定要匹配的去释放,不匹配的释放,结果是不一定的。
- 不要使用delete释放已经释放的内存块
- 不要使用delete释放已经释放不是new申请的内存
- 不要创建指向用一个内存的指针
- 如果使用new[ ] 分配内存,应该使用delete[ ]来释放
自动存储、静态存储、动态存储
- C++有两种存储方式:自动存储、静态存储、动态存储
自动存储
在函数内部定义的常规变量使用自动存储空间,意味着他们在被所属函数调用时自动产生,函数结束自动释放
静态存储
整个程序执行的过程中都存在的存储方式,是变量变为静态的方式是1.在函数外定义它2.申明变量的时候加上static: static double fee=45.3;
动态存储
new和delete运算符就提供了一种更加灵活地内存管理方式,这种称为自由内存管理方式或堆
8. 引用(&)
C++新增的一种复合类型,给已定义的变量取一个别名,两者用法相同。
- 引用和原变量的值和地址相同
int a =10; //定义一个变量a
int &c=a; //&符号放在定义时,不是取地址,而是引用。
//声明a的一个引用,c是a的一个别名
//a与c的地址是相同
- 对引用和原变量操作两者都会改变
int ratss = 123;
int& rodentss = ratss;
cout << "ratss=" << ratss<< endl ; // ratss=123
cout << "rodentss=" << rodentss << endl; // rodentss=123 两者的值相同
// 对引用改变,二者都改变
rodentss++;
cout << "ratss=" << ratss << endl; // ratss=124
cout << "rodentss=" << rodentss << endl; // rodentss=124
// 对源数据改变,二者都改变
rats++;
cout << "ratss=" << ratss << endl; // ratss=125
cout << "rodentss=" << rodentss << endl; // rodentss=125 对其中的一个进行++操作另一个值也会改变
// 二者地址相同
cout << &ratss << endl; // 010FFD38
cout << &rodentss << endl; // 010FFD38 两个地址相同
return 0;
- 引用与指针不同
int ratss = 123;
int& rodentss = rats;
int* p = &ratss;
//三者的值相同
cout << "ratss=" << ratss << endl; //ratss=123
cout << "rodentss=" << rodentss << endl; //rodentss=123
cout << "*p=" << *p << endl; //*p=123
//三者地址相同
cout << "&ratss=" << &ratss << endl; // &ratss=003EF6F4
cout << "&rodentss=" << &rodentss << endl; // &rodentss=003EF6F4
cout << "p=" << p << endl; // p=003EF6F4
-
可见:ratss(原变量) rodentss(引用) *p(指针) 三者等价,&ratss与&rodentss与p 三者等价
-
引用必须在初始化的时候进行赋值,但是初始化之后还可以引向其他的值
int rat;
int & rodent = rat ; 可以
int & aban;
aban = rat; 不可以
int temp =100 ;
int & opt = temp;
int str = 50;
opt = str; 可以 相当于赋值
此时 temp opt str 三者的是都为50
temp opt 的地址依然相同,与str的地址不同
常量的引用
int &a=12; //会报错
const int &a=12; //可以这样修改
数组的引用
- 数组的引用一定要把&和引用名加上()
int arr[12];
int (&p)[12]=arr; //一定要加()
int arr2[2][3];
int (&p2)[2][3] = arr2;
引用做函数的参数
void swapv(int a,int b)
void swapp(int & a,int & b)
void swapr(int *p,int *q)
// 三个函数的功能都是交换形参的值,就是形参的形式不同
int main()
{
int wallet1 = 100;
int wallet2 = 50;
//参数为原型,无法交换值
void swapv(wallet1,wallet2);
cout << wallet1 << wallte2 ;
// 参数为引用,可以交换
void swapp(wallet1,wallet2);
cout << wallet1 << wallte2 ;
// 参数为指针,可以交换
void swapr(&wallet1,&wallet2);
cout << wallet1 << wallte2 ;
按值传递参数的函数,输出没有交换两个值;
但是引用和指针方法都成果的交换了两个值
}
注:
- 按值传递函数swapv中变量a,b是复制的wallet1,wallet2的值的新变量,交换a,b的值并不会影响wallet1,wallet2的值
- 按值传递和按引用传递看似是,但是地址运算符&是的其按地址传递参数
- 如果想让****,同时又想使用引用可以使用常量引用,在函数原型和函数头使用const
double refcube (const double &ra); 当要修改ra的时候,就会发生错误
按值传递与按引用传递
- 按值传递一下都是正确的
double z=cube(x+2.3); z=cube(8.0); int k=10; z=cube(k); double yo[3]={2.2,3.3,4.4}; z=cube(yo[2]); - 按引用传递参数时就不能将算数表达式传递给函数了。
对于形式参数为const引用的C++函数,如果实参不匹配,则其行为类似于按值传递为确保原始数据不被改变,将使用临时变量来储存。
如果函数调用的参数不是左值或与相应的const引用参数的类型不匹配,则C++将创建类型正确的匿名变量,将函数调用的参数的值传递给匿名变量,并让参数来引用该变量。
- 尽可能使用const参数引用参数为常量数据
- 使用count可以避免无意中修改数据。
- 使用const是函数,能够处理const和非const的实参,否则只能接受非const的数据。
- 使用const引用,使函数能够正确生成并使用临时变量。
引用结构体
- 声明结构体的时候要加&,定义结构体的时候不需要加&
引用与指针的区别
- 引用声明要初始化,指针不用
- 引用初始化后就不能再引用其它空间,指针还可以指向其它空间
- 引用不占内存空间,指针占空间
- 引用效率更高(引用是对内存空间的直接操作,指针装的是地址,通过地址操作空间)
- 引用更加安全,指针可能偏移(指针可以做加运算指向下一个地址)
- 指针更加灵活,直接操作地址,C与C++都可以
9. 增强for循环
10.函数
函数的参数
- 函数在定义形式参数的时候如果要在定义的时候形式参数赋值,就要从右向左连续赋值。(把要赋值的放在右边)
void abu(int a, char'b',floar f=123.23) //从右向左连续的都是赋值的
{
}
函数的重载
函数名相同,参数不同(参数的类型、个数)的函数互为重载函数
void fan(int a)
{
}
void fan(int a, int b)
{
}
void fan(char c)
{
}
// 系统会自动根据要调用的参数的形式和个数调用相应的还是
内联函数
编译代码与其他程序代码关联起来,就是编译器将使用相应的函数代码替换函数调用。相当于#define,但是相较于#define更加安全
- 声明函数时是加关键词 inline
# include <iostream>
using namespace std;
inline double square(double x) { return x * x; }
int main()
{
double a = 3;
double b = square(a);
cout << b;
}
// 输出b为9,调用square(a),就用定义函数的函数体a*a来替换a
inline工具是C++新增的特性,C语言使用预处理器语句,#define提供宏。
默认参数
在定义函数时给形参赋值,该值为默认值,如果在调用函数时,对应的实参有值就用实参的值覆盖,默认值如果没有给实参赋值,就用默认值代替实参的值。
int harpo (int n,int m=4,int j=5);
// 该函数的m和j就是默认参数。
- 默认参数必须全部依次排列在右边。
- 实参也要按照形参的对应顺序调用的时候 不能中间跳过参数 beeps=harpo(3, ,8)这样不行。
函数 模板
当函数需要改变函数的参数类型,但是又不想,总是重复的定义相似的函数,把某些变量的类型当做变量,在调用的时候再输入具体想要的变量类型。
创建一个函数模板
template <typename T>
void Swaps(T& a, T& b)
{
T temp;
tmep = a;
a = b;
b = temp;
}
//函数为void类型,所以没有返回值,如果有返回值要写
这个函数是交换两个参数的值,其中template和typename是固定的,T代表着你要输入的函数返回值类型,输入完函数类型之后,函数体中的T用函数类型替换。
- 函数模板的实例化:隐式实例化、显示实例化
template <typename T>
T Maxs(T a, T b) // 该函数有返回值,返回值类型为要输入的类型,用T先代替
{
return a > b ? a : b;
}
int main()
{
// 函数模板的隐式实例化,由编译器去猜测函数模板的类型。
int n = Maxs(1, 4);
cout << n;
float m = Maxs(2.3f,4.0f);
cout << m;
// 函数模板的显示实例化,在函数后面用的<>中表明出来
double d = Maxs<double>(3, 4.5f);
cout << d;
}
11.数组
- C++与C的数组基本相同
int carrds[4]={3,6.8,4};
int hard[4];
hard[1]=2;
hard[2]=3;
hard[4]={2,3,4,5}; //不允许,只有在定义的时候可以这样用大括号赋值
double earn[4]={}; //如果大括号里为空,则把所有值都初始化为0
vector模板类(一种动态数组)
vector类似于string类,是一种动态数组。
- 使用new创建动态数组的替代品,使用new和delete来管理内存,但这种是动态的。
vector<int>vi;
array模板类
12.结构体
定义与C语言相同
与C语言不同的是C++在定义一个结构体的时候不需要写struct
struct inflatable
{
char name[10];
double volum;
int price ;
};
// 与C语言不同的是C++在定义一个结构体的时候不需要写struct
int main()
{
inflatable guest=
{
};
// 虽然不用写struct但是建议写上,提高阅读效率
inflatable pal=
{
"Glorious",
3.12,
33.4
};
}
- 定义初始化结构体的时候,如果大括号里为空,则所有被赋值为0
13.共用体(union)
共用体是一种数据格式,它能够存贮不同的数据类型(只能储存int, long,double类型)
语法与结构体相似
union one4all
{
int int_vall;
long long_vall;
double double_vall;
}
one4all pail; //定义一个one4all类型的数据
pail.int_vall=15;
cout << pail.int_vall;
14.指针
- 指针是一个变量,他储存的是值的地址而不是值本身
- 一定要在指针应用解除引用运算符*之前(定义指针的时候),将指针初始化为一个确定的、适当的地址,这是使用指针的金科玉律
- 指针在32位操作系统中占4个字节,64位中占8个字节
C风格的指针:
+ int *p; // 强调*p是一个int类型的值
C++风格的指针
+ int* p; // 强调int*是一种数据类型——指向int的指针
C++会将数组名解释成为第一个元素的地址
double wages[3]={123,345,456,};
double* pw = wages; //指针保存的是地址值,应为&wages,但C++会将数组名解释成为第一个元素的地址,就不用加&了。
- 指针加一,指向下一个地址,增加的是一个数据类型所占的字节数
空指针是不能被访问的:
空指针:int * p = null,p就是空指针
野指针:指针指向一个非法的空间。
空指针和野指针都不是我们自己申请的地址,不要随意访问他
结构体指针
struct student
{
string name ;
int age ;
};
int main()
{
student s = {"张三" , 18 }
// 结构体指针
student* p = &s ;
}

本文档详细介绍了C++的基础知识,包括main函数、常量、关键字、字符串操作、输入输出、命名空间等内容。此外还深入讲解了结构体、共用体、指针等高级主题,并对比了引用与指针的区别。
4820

被折叠的 条评论
为什么被折叠?



