c++学习笔记-第一部分 基础部分

c++学习笔记,不一定每一个都写案例,主要是补充和留下印象吧。

第一个c++程序

//引入头文件
#include <iostream>
//入口
int main()
{
    //输出一句话
    /**
    1.std::cout 向控制台输出内容
    2.<<        输出运算符
    3.""        输出内容
    4.hello world 
    5.\n        回车
    6.;         结束
    */
    std::cout << "Hello World!\n";
}

C++输出数据

std::cout << "Hello World!\n";

使用变量

int a;
a = 10;

注释

1.//
2./**/

常量

const int a = 10;

数据分类

(1)数字:0-9
(2)字符:单引号括起来的 ''
(3)字符串:双引号括起来的 ""

输出数据步骤

(1)Std::cout可以输出各种类型的数据
(2)操作符拼接多个数据项
(3)Std::endl换行使用
(4)Using namespace std;缺省命名空间

程序的注释

(1) 程序添加说明文字,
①单行注释
②多行注释

使用变量

(1) 变量是存储内存变量的简称,用于存放临时数据的。
(2) 属于之前需要先声明
语法:数据类型 变量名
(3)常用的数据类型有:int、float、double、char、string、bool
(4)代码

#include <iostream>

int main()
{
    char c = 'A';
    int num = 10;
    std::string name = "垃圾";
    bool sex = false; //ture为1  false为0
    std::cout << c << "  " << num << "   " << name << "  " << sex;
    std::cout << "Hello World!\n";
}

标识符命名

C++输入数据

(1)C++输出类型
①控制台节目输入
②文件中读取
③数据库中读取
④网络中读取
⑤输入方式
(2) 输出案例

Std::cin >>变量名

(3)注意

  1. bool只能填入0和非0
  2. 输入数据和变量数据类型不匹配,导致结果不确定
  3. 代码
string name;
cin >> name;
std::cout << "Hello World!\n"<<name;

算术运算

基本运算

(1) 算术运算包含了:+ - * / %
(2) 只适用于整数和浮点数
(3) 取模只能使用于整数

自增和自减运算

(1) ++变量名、变量名++、--变量名、变量名--

赋值运算

1.+=
2.-=

c++11初始化赋值

old

int a = 100;
int b(100);
int c = (100);

new


```c++
int a = 100;
int b{100};
int c = {100};

函数

函数的位置

(1) 在main上面定义,下来写内容
(2) 在main的上面写内容
(3) 函数可以多次声明,但是实现只有一个
(4) 函数的声明也可以写main函数中,必须放在使用之前,否则会报错。

函数参数的传递

(1) 函数调用,调用这将参数传递给函数的参数
① 实参:可以是常量变量表达式
② 形参:函数调用的参数
(2) 函数中修改形参的值不会影响实参。
(3) 代码

#include <iostream>
int max(int a, int b);
int min(int a, int b);
int main()
{
    int a = 10;
    int b = 11;
    std::cout << "max:" << max(a,b) << std::endl;
    std::cout << "Hello World!\n";
}

int max(int a, int b) {
    return a > b ? a : b;
}

int min(int a, int b) {
    return a < b ? a : b;
}

函数分文件编写

(1) 使用头文件和源文件在编写代码
(2) 在使用的时候通过#将头文件加进去
(3) 可以写到头文件中的东西:头文件、命名空间、全局变量、函数声明,数据结构和类的声明等
(4) 源文件:函数的定义、类的定义。

Sizeof运算符

(1) Sizeof(数据类型) 得到数据类型或者变量占用的内存空间
(2) 32位和64为可能结果不一样
(3) String不是基本数据类型,sizeof(string)没意义
(4) 代码

cout << sizeof(int) << endl;
cout << sizeof(a) << endl;

C++的基本数据类型

(1) int float double char bool string(不是基本数据类型,但是比较重要)

int类型

整型的基本概念

(1) C++使用int关键字声明变量,实际是integer的简写
(2) 声明的时候可以在int关键字之前加signed、unsigned、short、long四种修饰符

① Signed:有符号的,可以表示正数和负数

② Unsigned:无符号的

③ Short:短的

④ Long:长的

(3) C++中没有整数的取值范围,取值返回根据组合来计算得到

整数的书写

(1) 二进制:书写必须以0b(B)开头

(2) 八进制:
① 必须以0开头
② 0-7
(3) 十进制
(4) 十六进制:
① 0x开头

整数的坑

(1) 书写十进制不要在前面加上0,会被认为是八进制

longlong类型

  1. vs中long是4个字节
  2. liunx中long是8个字节
  3. long long 类型的整数,至少是8个字节,并且与long的长度一样长

浮点型

  1. 浮点型包括float 、double、long double
  2. 字符数据类型;
    a) 内存占用一个字节,使用单引号
    b) 不存放字符本身,只存放编码
    c) 内存中存储都是二进制
  3. ASCII:33个控制字符 95个可显示字符
  4. 字符的本质
    a) 字符本质是整数,取值范围是0-127
    b) 书写的时候使用单引号,也可以使用整数
    c) 显示的时候可以是整数,也可以是整数
    d) 可以和整数进行运算

原始字面量

是不需要转义,直接使用他的直接含义

#include <iostream>
using namespace std;

int main()
{
    string path = "c:\\user";
string path = R"(c:\user)";
//前后必须一致  否则会报错
string path1 = R"aaa(c:\user;)aaa";
    cout << "Hello World!\n";
}

字符串

(1) C++风格:string var = “字符串”; 类
(2) C风格:char[] ch = “字符串”; 字符数组

数据类型的转换

(1)计算机进行运算的时候,要求操作数类型相同的大小和存储方式
(2)转换方式:
i. 自动转换
ii. 强制转换

数据类型的别名

1.别名的目的
i.创建别名,方便书写和记忆
ii. 创建与平台无关的数据类型,提高程序的兼容性
2.兼容性的写法

typedef long int lint;判断使用的机器

3.别名可以原原本本的代替原名
4.语法

typedef 数据类型名  别名

指针

(1) C++通过&得到变量的其实地址
(2) 语法

i.  &变量名  取得数据的地址

(3)指针用于存放变量的地址 (起始地址)
(4)函数中使用

void printInfo(int* a) {
    cout << *a << endl;
    *a = -1;
}
int main()
{
    int a = 0;
    printInfo(&a);
    cout << a << endl;
}

(5)优点:可以提升性能,较少数据的copy

(6)没有指定值的指针,值是乱七八糟的

(7)指针存储的是地址,所有指针的变量名存储的是地址

(8)*对指针进行解引用

指针用于函数的参数

(1)指针是指向的地址的,如果函数使用指针作为参数,那么使用地址传参

(2)既然是指针,那么在使用的使用的时候,通过解引用得到值。

(3)如果在函数中是通过解引用改变值,那么也会改变原来的值

(4)好处

  • 函数中修改实参的值
  • 减少拷贝,提升性能

值传递和地址传递

使用常量

常量是程序中固定不变的数据

(1)const修饰
(2)在程序的任何地方都可以的
(3)使用它修饰指针

常量指针

(1)语法:const 数据类型 变量名
i. 不可以使用解指针的方法设置值
ii. 注意
(2)指向的变量可以改变,值不可以改变(
p =xx值不可以改变)
(3)一般用于修饰函数的形参,表示不希望改变值
(4)如果用于型参,虽然指向对象可以改变,但是没意义

指针常量

(1)语法:数据类型 *const 变量名
(2)指向的变量对象不可以改变
(3)注意
i. 定义的时候必须初始化,否则没意义
ii. 可以通过解引用方法修改地址中的值
iii. 代码

Int* const p = &a;
*p = 13;初始化必须设置值   并且值可以修改

常指针常量

(1)语法:const int *const int

(2)宏常量

i. 一般在main函数之上声明的,使用大写字母

ii. 语法:

#define NAME C++;

void关键字

(1)C++中,void表示无类型

(2)作用:
i.函数返回值void
ii.参数设置为void,表示不需要参数
iii.void*作为函数参数,表示可以使用任意类型的参数

(3)注意:

i. 不能使用void声明变量,不可以代表一个真实的变量

ii. 不能对void*指针直接解引用

iii. 把其它类型的指针赋值给void*指针不需要转换

iv. 把void*指针赋值给其他类型的需要转换

内存空间

内核空间 栈空间 堆空间 常量 代码

堆和栈的区别

(1)管理方式不同:栈是自己回收的,出作用域就会自己回收,堆需要自己释放

(2)空间大小不同:堆是物理空间决定的,栈一般只有8M

(3)分配方式不同

(4)是否存在碎片

动态分配内存new和delete

(1)使用堆内存的步骤

i. 声明指针

ii. 使用new向系统申请一个内存,让指针指向这块内存

iii. 通过解引用的方法,使用这一块内存

(2)语法:new 数据类型(初始值)

(3)申请成功分配一块地址,如果申请失败,就是一块空地址

(4)释放delete 地址

(5)注意

i. 动态分配内存没有变量名,只能通过指针来操作内存中的数据

ii. 如果动态分配内存不使用了,必须要释放

iii. 动态分配的内存生命周期与程序相同

iv. 指针作用域失效,指向的内存也不会释放

v. 指针跟踪分配内存的时候,不可以跟丢。

二级指针

空指针

(2)在c或者是c++中,都可以使用0或者NULL表示空指针,在没有赋值之前给它设置空,代表没有指向任何地址

(3)使用空指针的后果

i. 程序崩溃

ii. 对空指针执行delete,系统会忽略该操作,不会出现异常,内存释放后,也应该设置为null。

(4)为什么指向空指针会崩溃

i. Null指针分配的分区,范围是0x0000-0x0000ffff这个区域是空闲的,没有任何物理存储与之对应,任何读写都会发生异常

(5) C++11的nullptr

i. 使用0或者NULL会产生歧义,所以建议使用(void*)0

野指针

(1)野指针就是一个没有指向一个有效合法的地址

(2)如果访问野指针就会发生崩溃

(3) 出现野指针的情况

i. 指针定义的时候没有初始化,值是不确定的

ii. 使用了动态分配的内存,内存释放了,指针不会置空,但是指向已经失效

iii. 指针指向变量已经超过了作用域

(4)规避方法

i. 指针在定义的时候,如果无指向,就指向nullptr

函数指针

(1)函数的二进制代码存放在内存四区中代码段,函数的地址是它在内存中的起始地址,如果将函数地址作为参数传给函数,就可以灵活的调用其他函数

(2)使用函数指针的步骤

i. 声明函数指针

ii. 让函数指针指向函数的地址

iii. 通过函数指针调用函数

(3)代码演示

i.声明函数指针

int max(int a,int b);
int (*maxa)(int,int);  可以和上面一样,也可以直接这么写就完事了
int max(int a,int b){
    return a > b ? a : b;
}

int a = 10;
int b = 20;

//使用函数指针名
void (*pmax)(int,int);
pmax = max; //函数名字就是函数的地址
pmax(a,b)  //c++写法
(*pmax(a,b));//c的写法
max(a,b);

(4)函数指针有什么作用

我也解释不清楚,直接一个案例把

void log(){
}

void printLog(void (*plog)()){
    logpre();
    log
    logend();
}

2.必须提供指针类型(返回值和函数列表)

数组

数组:一维数组 二维数组 多维数组

创建数组

(1)声明数组:数据类型 数组名[数字长度]

  • 数组的长度必须是整数 常熟 表达式
int bh[3];
string name[3];

数组的赋值

bh[0] = 1;

占用空间

sizeof(bh); 类型 * 长度

sizeof只适用于基本数据类型,其他的没有意义

初始化

声明的时候初始化

类型 nameArr[length] = {v1,v2,……};  指定值
类型 nameArr[] = {v1,v2,……};  
类型 nameArr[] = {0}

数组清零

memset函数将数组清零

void *memset(void *s,int v,int size)

memset(bh,0,sizeof(bh));

数组复制

memcpy()将数组中的全部元素复制到另一个相同的数组


## 引用

### 引用概念以及作用

1.引用是c++新增的复合类型

2.它是已定义变量的别名

3.主要用途是函数的形参和返回值。

4.语法
```c++
数据类型 &引用名 = 原变量名

5.引用取值

int a = 3;
int &ra = a;

cout<<"a地址:" <<&a << "a的值:" << a <<endl;
cout<<"ra地址:" <<&ra << "a的值:" << ra <<endl;

数组和指针

地址+1,一般加的是地址+数据类型大小,所以数组+1是下一个数据的值。

输出地址的方法
cout<< (long long)&a[0] <<endl;
cout<< (long long)&a[1] <<endl;
cout<< (long long)&a[2] <<endl;
cout<< (long long)&a[3] <<endl;
int *p = a;
cout<< (long long)p <<endl;
cout<< (long long)p+1 <<endl;
cout<< (long long)p+2 <<endl;
cout<< (long long)p+3 <<endl;

数组的越界

合法的数组下标

一维数组用于函数参数

数组下标取值解释为首地址+下标解引用取值

地址加下标 p[1] 当前地址开始向后一个 p[2]当前地址向后两个

数组操作:

char a[20];
int *p = int(*)a;  //char类型变为了int类型  操作不超过20,就不会存在问题

数组用于函数

传递的数组,在函数中是指针,使用sizeof得不到数组的长度

new创建数组

普通数组在栈上分配,更多的在堆上

数组类型 *指针= new 数据类型[size];

释放:
delete[] 指针;

遍历指针

*(arr+i)遍历数组   指针解引用

注意

  • 动态创建的,不可以使用sizeof运算符
  • 可以使用数组和指针的方法操作数组
  • 必须使用delete释放
  • 栈上分配空间,如果内存超出会异常
  • 大量数据需要在堆上分配

new分配可以堆超出的,给出一个空地址

int *a = new(nothrow)int[maxsize];

if(a == nullptr){

}else{

}

c风格字符串

  • c++字符串是string,可以自动扩展,不需要担心内存
  • string封装了c的字符串
  • c风格的更加方便/高效

c风格的字符串

如果char数组末尾包含了\0,那么就是一个字符串。所以使用c字符的时候,需要多留一个存放\0

char name[20];
cout<<name<<endl;  会显示遇到0结束(c/c++都是)

清空字符串就是将所有的数据都设置为0

方法一:
char name[10] =  {0}; //清空
方法二:
memset(name,0,sizeof(name));
方法三:
将第一个设置为0

字符串赋值或复制

strcpy(name,"hello");
strncpy(name,"hello",3);//指定个数小于字符长度没有问题 ,但是小于就会存在问题

毕竟字符出结尾是\0,所以建议每次最好清零

字符串拼接

strcat(dst,src);

结构体

定义结构体就是告诉编译器,定义了一个新的数据类型,每个成员是什么类型

结构体声明变量

struct People{
    string name;
    int age;
}

//声明变量  c中必须struct c++中可以不写
struct People p;

访问成员
p.name = "wk";
p.name = 10;

cout << "name :" << p.name;

注意:

  • 结构体名是标识符
  • 结构体成员可以是任意类型的数据
  • 定义结构体可以放在代码的任何地方,一般放在main的上面或者头文件中
  • 结构体一般放在使用之前
  • 结构体成员可以使用c++的类,但是不提倡
  • 结构体中可以有函数,但是不提倡(c++)
  • 结构体可以给初始值(c++11)

结构体的细节

  • 创建的时候可以设置值
People p = {v1,v2,……};
Poeple p1 = {0};
  • 创建结构体的时候,创建结构体变量
struct People {
    char name[20] = "kw";
    int age = 100;
} p;
  • 还可以初始化
struct People {
    char name[20] = "kw";
    int age = 100;
} p = {"cs",100};

1.占用内存的情况

使用ziseof可以计算结构体的大小。但是结构体占用内存不一定等于全部成员占用的内存大小,因为需要内存对齐

内存对齐,

2.清空结构体

创建结构体没有初始化,成员变量中存在垃圾值,使用memset清楚数据中的值,只使用于c++中的数据类型

memset(&strp,0,sizeof(strp))

3.结构体的复制

  • memcpy()将结构体中的成员复制到另一个相同类型的结构体中
  • 也可以使用==

结构体指针

结构体是一种自定义的数据类型,使用结构体可以创建变量

(1)基本语法

struct People p; //声明结构体变量
struct People *pst = &p; // 结构体指针

(2)访问成员

指针名里面是地址,解引用是结构体,结构体.
(*指针名).成员名

指针名-> 成员变量

(3)用处:
作为函数参数, 用于动态分配内存

枚举

enum 枚举名{v1,v2}

enum colors {
    red,vv,ss
};
//值为012
colors f = red; //对
colors xx = 0; //x

值虽然是0123,但是不可以直接设置

(2)注意事项和细节

  • 枚举创建变量只能在枚举范围内
  • 枚举和变量作用域一样
  • 可以显示枚举的值
  • 给枚举指定值
  • 整数强制转换为枚举 枚举类型(整数)

引用

引用是c++新增的符合类型,是已经定义变量的别名,主要用途是函数形参以及返回值

1.声明语法:

数据类型 &引用名 = 原变量名 
int a = 0;
int &ra = a;

2.注意事项

  • 引用的数据类型与变量名一致 int int
  • 引用名和原变量名可以互换
cout<< "a的地址"<< &a << "a的值:"<< a << endl;
cout<< "ra的地址"<< &ra << "ra的值:"<< ra << endl;

两个输出都是相同的

ra = 9;
他们的值都发生了改变
  • 必须在声明的时候初始化
引用初始化后值是不变的
int a = 10;
int ra = &10;

int b = 3;
ra = b; // a = 3

  • c/c++使用&符号来指示/取变量的地址

引用的本质

指针常量的伪装

int a = 3;
int &b = a;
int * const rb  = &a;

引用用于函数参数

将函数形参声明为引用,调用的时候,形参为实参的别名,这个叫引用传递,引用的本质是指针,传递的是地址,形参会影响到实参

优点:

  • 传引用代码简洁
  • 不需要传递二级指针
  • 引用的属性和特别之处

指针:用于函数参数和动态分配内存

传值案例

//值传递 f(1,2)
int f (int a ,int b){
    a = 10;
    b = 0;
    return a;
}
//指针传递 f(&a,&b)
int f (int* a ,int* b){
    *a = 10;
    *b = 0;
    return a;
}
//引用传递 f(a,b)
int f(int &no,int &ss){
    a ,b
}

引用用于返回值

函数返回值引用语法

int *fun(){

}

调用
int &d = fun();

注意:

  • 如果返回值是局部的,那就是野指针
  • 可以返回
    • 引用参数
    • 类的成员
    • 全局变量
    • 静态变量

注意事项

1.引用数据类型与原来的数据类型相同

2.引用与原变量名可以互换,值与内存单元相同

3.必须在声明之前初始化,初始化后不可变

引用的本质

他是指针常量的伪装

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容