代码注释没有高光,小编实在改不过来了。
编译时将函数的声明放到.h 的头文件中,相似函数类型的放在同一个.cpp文件中。
cpp
预处理和宏
预处理:
#include<iostream>
#define PI
#include <omp.h>
#endif
宏
#define PI 3.14
double len(double r){
return 2.0 * PI * 2;
}
//宏PI可以认为就是3.14,但是PI并不是变量而是宏
std::ostream cout;
cout << "hello." << endl;
ostream: (output stream) 被保护的无法为重新赋值给cout以外的变量
允许你在当前作用域内直接使用标准库中的名字,而不需要在每个名字前都加上 std:: 前缀。
std: 命名空间(namespace)
endl: (endline)这一行的结束,输出一个换行符
<<: 操作符
cpp
#include <iostream>
using namespace std;
int main(int argc, char ** argv)
{
for (int i = 0; i < argc; i++)
cout << i << ":" << argv[i] << endl;
}
数据类型
int
cpp
int i = 0; //声明一个变量,数据类型为整数型(integer),并将其初始化为零
int: 整数型
整数型一旦声明必须进行初始化,最常用初始化为零!!!!在不同架构下未进行初始化会导致错误产生
unsingned int //无符号整数型
singned int //有符号整数型
整数一般为32位,有符号型最高位是存符号的,如果是0表示正数、如果是1表示负数
无符号整数型32位全部用来存数,没有符号位,表示为正数
int默认是(singned int)有符号整数型
overflow:整数溢出
short int //让整数短一点,少一些字节
long int //让整数长一点,长一些字节
long long int //long int不够用时,用long long
<<
cpp
#include <iostream>
using namespace std;
int main()
{
unsingned int a = 56789;
unsingned int b = 56789;
unsingned int c = a * b;
cout << "c = " << c << endl;
cout << "sizeof(c) = " << sizeof(c) << endl; //返回c字节长度
return 0;
}
char
char本质上来说就是一个8位数的整数
cpp
singned char;//取值范围从-128到+127
unsingned char; //取值从0到255
char标准并未规定是singned char 还是unsigned char
cpp
#include <iostream>
using namespace std;
int main()
{
char a1 = 'C';
char a2 = 80;
char16_t a3 = u'天';//16位表示汉字
char16_t a4 = U'依';//32位表示汉字
cout << a1 << ":" << a2 << endl;//默认输出为字符
cout << +a1 << ":" << +a2 << endl; //"+a1"输出为正整数
cout << "sizeof(a1) = " << sizeof(a1) << endl; //返回a1字节长度
cout << a3 << endl;
cout << a3 << endl;
return 0;
}
//此为c++11
bool
c语言的标准并没有规定bool是数据类型,其结果为true(1) 或false(0)。
cpp
#include <iostream>
using namespace std;
int main()
{
bool b1 = true;
int i = b1;
bool b2 = -256;
cout << "b1=" << b1 << endl;
cout << "b2=" << b2 << endl;
}
//当一个值转成bool如果不是零,其余结果为1
//c语言中可以调用<stdbool.h>
size_t
是一个无符号整数,类型与sizeof,一般用size_t表示内存大小
cpp
<csdint>
int8_t //有符号的8位int型 INT8_MIN int8最小值
int16_t INT16_MIN
int32_t INT32_MIN
int64_t INT64_MIN
uint8_t //无符号的8位int型 INT8_MAX int8最大值
uint16_t INT16_MAX
uint64_t INT32_MAX
float
cpp
#include <iostream>
#incluse <iomanip>
using namespace std;
int main()
{
float f1 = 1.2f;
float f2 = f1*1000000000000;
cout << std::fixed << std::setprecision(15) << f1 << endl;
cout << std::fixed << std::setprecision(15) << f2 << endl;
return 0;
}
这个代码结果f1并不是准确1.2,是因为flout数值之间无法完全表达这个区间,只能在这个数之间采样,取一些代表性的点来表示,无法用有限的位数表达所有的小数
cpp
float f1 = 2.34E+10f;//2.32乘e的10次方,f为浮点数;
float f2 = f1 + 10;//f2 == f1
//量化精度不够导致,采样时 间隔性在这个区间代表性取些点
if (fabs(f1-f2) < FLT_EPSILON) //FLT_EPSILON
doubt
双精度浮点数
算数运算
cpp
const float PI = 3.14f //const 类型限定符 表示PI的类型和数值无法被修改
auto a = 2;
auto c = 2.3; //auto 灵活的数据类型,数据类型主要看在初始化时它是什么类型,且初始化后类型不再发生改变
a++;
++a //加加在前先增再赋值,加加在后先赋值再增
~a;//按位取反
a & b //与位运算,全1出1
a | b;//或位运算,有1出1
a ^ b;//异或运算,相同出0,不同出1
类型转换
int num = (int)'C'; //显示类型转换
int a1 = 1.9 //结果为1
short num_short = 650000;//会输出成负数,超出short类型二进制的范围,最高位会被置为一
float f = 17 / 5;// f结果为3.f,是整数除法,整数为是3,所以结果为3.f
float f = 17 / 5f;//f结果为3.4f,是浮点数除法,结果为3.4f
//算数运算一共四种算数操作,分别是int,long,float,double
unsigned char a = 255;
unsigned char b = 1;
int c = a + b; //c = 256 ,a会转成int型255、b会转成int型1
数组arrays
cpp
#include <iostream>
using namespace std;
int main(){
int num_array[5];
for(int idx = -1; idx <= 5; idx++)
num_array[idx] = idx * idx;
for(int idx = -1; idx <= 5; idx++)
cout << num_array[idx] << endl;
//这个代码并不会报错,而是向下移位,而且类似程序可能会超出内存边界,导致操作系统会杀死程序
int array1[4] = {9,8,7,6};
int array2[4];
array2 = array1; //error! 数组是指向数组的地址也就是指针常量,无法被该代码赋值,可用下列代码进行赋值
//array2[0] = array1[0];
//array2[1] = array1[1];
for(a = 0; a < 4; a++)
{
array1[a] = array2[a];
}
for(i = 0; i < 4; i++)
{
cout << array2[i] << " ";//中间空格隔开
}
cout << endl;
return 0;
}
cpp
二维数组
void int_array(float mat[][3], size_t rows, size_t cols) //二维数组第二项一定要填写,因内存为一维排列,其是用于判断内存区域。
字符串Stings
cpp
数组类型字符串
char good_ping[5] = {'g', 'o', 'o', 'd','\0'};//数组字符串结束位为字符整数0
char name[10] = {'a', 'b', 'c', '\0', 'd', 'e'};
cunt << strlen(name) << endl; //字符串长度为3
常量字符串
char name[] = "abcd"; //name[5],字符串结尾有隐藏的ascii的\0
字符串拷贝
char *strncopy(char *dest, const char *src, size_t count);//将src中count数拷贝到dest
字符串连接
char *strcat(char *dest, const char *src);//将src链接到dest后面
std::string str1 = "Hello";
std::string str2 = "world";
std::string result = str1 + str2;//string并不会检查越界问题
字符串比较
int strcmp(const char *lhs, const char *rh)//前大后小返正值,前小后大返负值,首位相同向后比,完全相同返回零
结构体、联合体、枚举类型
结构体
cpp
#include <sting.h>
#include <stdbool.h>
struct student{
char name[4];
int born;
bool male;
};
int main(){
struct student stu = {"yu", 200, true}; //stu变量数据类型是student结构体
//strcpy(stu.name, "yu");
//stu.bron = 200;
//stu.male = true;
struct student stu[100];
stu[50] born = 203; //stu变量中第51为203
}
cpp
#include <sting.h>
#include <stdbool.h>
typedef //自定义类型
struct _student{
char name[4];
int born;
bool male;
} student; //student 相当于struct _student //创建类型别名
int main(){
student stu = {"yu", 200, true}; //stu变量数据类型是student结构体
//strcpy(stu.name, "yu");
//stu.bron = 200;
//stu.male = true;
student stu[100];
stu[50] born = 203; //stu变量中第51为203
}
在c++中struct与class类似,只是在public/private不同,调用相同,还要注意内存对齐
联合体
cpp
union ipv4address{
std::uint32_t address32;
std::uint8_t address8[4];
}//union定义接近struct,union所有成员共享一个内存。所有成员有相同的地址
指针
cpp
#include <iostream>
using namespace std;
int main()
{
int num = 10;
int * p1 = NULL, * p2 = NULL; //指针变量p1,p2初始化为零(NULL)
p1 = #//将指针变量p1指向num地址,&为取地址
p2 = #//p1,p2指向同一内存,即num的地址
cout << "num = " << num << endl;// num = 10;
*P1 = 20; //*为取指针地址的值,将num的值修改为20
cout << "num = " << num << endl;//num = 20;
*P2 = 30;//将num的值修改为30
cout << "num = " << num << endl; //num = 30;
cunt << "num = " << *p1 << endl;
return 0;
}
cpp
#include <iostream>
using namespace std;
struct student{
char name[4];
int born;
bool male;
};//声明结构体
int main(){
student stu = {"yu", 2000, true};//初始化
student * pstu = &stu; //声明pstu指针变量,指向stu变量的地址。也就是将pstu指针,指向student结构体的首地址
strncpy(pstu->name, "li", 4);//指针指向name成员变量,并将其拷贝为li
pstu->born = 2001;
(*pstu).born = 2002;//取指针地址值中的born
pstu->male = false;
cout << stu.name << " was born in " << sru.born << ". Gender :"
<< (stu.male ? "male" : "female") << endl;
printf("adderss:%p\n", pstu); //c
cout << "address of pstu: "<< pstu << endl; //c++,取地址
cout << "address of stu: "<< &stu << endl;
cout << "address of name: "<< &(pstu->name) << endl;
cout << "address of born: "<< &(pstu->born) << endl;
cout << "address of male: "<< &(pstu->male) << endl;
return 0;
}
指向指针的指针
指针本身是变量,可以再用一个指针指向该指针
cpp
#include <iostream>
using namespace std;
int main(){
int num = 10;
int * p = # //
int ** pp = &p;
*(*pp) = 20;//(*pp)为取pp(指向指针的指针)的值,也就是p中存储的值(num的地址),*(*pp)取num的地址
cout << "num = " << num << endl;
return 0;
}
指针常量
cpp
int num = 1;
int another = 2;
const int * p1 = # //指针指向的内容不可以透过这个指针去修改
*p1 = 3; //error
num = 3;//ok num变量自身可以修改
int * const p2 = # //指针指向的内容可以透过该指针修改,但是指针指向的内容无法被修改
*p2 = 3; //ok
p2 = &another; //error
指针和数组
数组可以看成指针常量,数组地址无法进行修改,对数组取地址还是数组本身,而不是指针的指针
cpp
#include <sting.h>
#include <stdbool.h>
typedef
struct student{
char name[4];
int born;
bool male;
} student;
int main(){
student students[128];
printf("&students = %p\n", &students);
printf("students = %p\n", students);
printf("&students[0] = %p\n", &students[0]); //地址相同
student * p = students;//students 本身是个指针,将students的地址赋予p
p[0].born = 2000;
p[1].born = 2001;
p[2].born = 2002;
}
cpp
//指针单手操作,指针加减,是加减元素
#include <iostream>
using namespace std;
#define print_array(arrray, n)\
for (int idx = 0; idx < (n); idx++)\
cout << "array[" << idx << "] = " << (array)[idx] << endl;
//宏定义 ,因宏只能在一行用换行转义符(\).
int main(){
int num[4] = {0, 1, 2, 3};
print_array(num, 4);
int * p = num +1;//int型占四字节,指针是对num向上偏移四字节,即偏移到num[1]
p++;//指针再次偏移,到num[2]
cout << "num = " << num << endl;
cout << "p = " << p << endl;
*p = 20; //num[2] = 20
*(p-1) = 10;// num[1] = 10,检查指针是否越界
p[1] = 30 //num[3] = 30,
print_array(num, 4);
return 0;
}
动态内存管理
在申请内存之后,手动释放内存,未释放容易发生内存泄露
cpp
//c 申请内存采用malloc
int * p = NULL;
p = (int*) malloc(4 * sizeof(int)); //申请了四个4字节内存,并将其转化为int型,指向变量p
free(p);//释放内存
cpp
//c++,申请内存采用new或new[],new是操作符
int * p1 = new int; //new int 是个表达式,结果就是这个操作的内存地址。其调用默认初始化(default initializer)
int * p2 = new int(5);//申请一个整数初始化为5,将其地址赋值给指针p2
int * pa1 = new int[16]; //申请16乘4的字节,16个int
int * pa2 = new int[16]();//():将其初始化为零
int * pa3 = new int[16]{};//():将其初始化为零
int * pa4 = new int[16]{1, 2, 3};//将前3个赋值为1,2,3 其余置为零
student *psa1 = new student[16];//申请16个结构体,指向指针psa1
student *psa2 = new student[16]{{"li", 2000, 1}, {"li", 2000, 1}};
//释放内存(delete)
delete p1;
delete p2;
delete pa1;
delete []pa2;//因为是int型没有本质区别
delete psa1; //因为psa1是结构体,当释放内存时调用析构函数,而psa1只是调用第一个元素的析构函数,释放第一个元素的内存
delete []psa2;//psa2是调用所以元素的析构函数,释放所有内存
functions 函数
函数是为了编程更加模块化
cpp
#include <iostream>
using namespace std;
int foo(int x)
{
x += 10;
return x;//也是个拷贝
}
int fooa(int * p)
{
(*p) += 10;
return *p;
}
int main(){
int num1 = 20;
int nmu2 = foo(num1);//相当于将num1拷贝到x,num1值没有被修改
int *p1 = &num1; //将指针p1中num1的地址拷贝到p指针中,p指针指向num1,当修改p指针的指向的值时(*p)num1也会被修改。
int nmu2 = fooa(p1);
return 0;
}
//这个代码函数的每次调用都用进行内存的拷贝,十分占用占用内存,解决办法下面参考嘿嘿
引用(reference)
c++中的概念,c中没有。一个reference实际上是一个变量的或一个对象的别名。
cpp
#include <iostream>
using namespace std;
int foo(int &x)//数据类型后加&表示引用,当修改这个值时,num也会被修改,与指针类似,但无需进行与指针的检查以及防止指针单手操作,导致内存越界
{
x += 10;
return x;
}
int main(){
int num = 10;
int nmu2 = foo(num);
cout << "num = " << num << ", nmu2 = " << nmu2 << endl;
return 0;
}
//如果要防止引用对原变量或对象进行修改,可以加const数据限定符
//float mmatrix_max(const struct Maxtrix mat){}