C++学习笔记

news2025/1/18 17:01:28

C++学习笔记

学习视频资料

随手记

vector是一个能够存放任意类型的动态数组
unordered_set 不能放重复元素的容器 emplace放入
std::cin.get(); //使控制器不会立马关闭,保持窗口打开
总是通过 const引用传递对象
默认 动态链接
static 静态链接(只在当前文件下使用)
导入头文件,复制其中所有内容粘贴在.cpp中
sizeof(x) x占的多少字节
count = sizeof(x) / sizeof(type)
i++ :先引用后增加,先在i所在的表达式中使用i的当前值,后让i加1
++i :先增加后引用,让i先加1,然后在i所在的表达式中使用i的新值
直接传递值和引用传递:直接传递值相当于复制一下传入,原本的值保持不变;引用的话内存地址
定义一个字典: unordered_map<int, int> dic;
由于 C++ 未提供自带的链式哈希表,因此借助一个 vector 按序存储哈希表 dic 中的 key ,第二轮遍历此 vector 即可。
排序:sort(nums.begin(),nums.end());
字符串:单引号是字符型,双引号是字符串型
使用stirng的substr函数, 其中第一个参数是起始位置, 第二个参数是子串的长度 s.substr(pos, len)
replace(#include < < <string > > >)
用法一:用str替换指定字符串从起始位置pos开始长度为len的字符,string& replace (size_t pos, size_t len, const string& str);
用法二:用str替换迭代器起始位置 和 结束位置 的字符string& replace (const_iterator i1, const_iterator i2, const string& str);
用法三:用substr的指定子串(给定起始位置和长度)替换从指定位置上的字符串string& replace (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);
insert
在原串下标为pos的字符前插入字符串str
动态规划:斐波那契数列需要对中间值取模,因为中间值会太大超出内存,整数溢出

basic_string& insert (size_type pos, const basic_string& str);

str从下标为pos1开始数的n个字符插在原串下标为pos的字符前

basic_string& insert (size_type pos, const basic_string& str, size_type pos1, size_type n);

在原串下标为pos的字符前插入n个字符c

basic_string& insert (size_type pos, size_type n, char c);

“1>>n”为将二进制码向右移动n位

C++是如何工作的

Compile

.cpp -> .obj(机器代码文件)
属性>预处理器>预处理到文件:可以生成.i文件,查看具体生成的代码,但是不会生成.obj
属性>输出文件>汇编程序输出:可以生成.ASM文件,查看具体的硬件代码
Error: Cxxxx

Link

.obj -> .exe(可执行文件)

Error: LNKxxxx

C++变量

int - 2 31 2^{31} 231 ~ 2 31 2^{31} 231 4个bytes,每个8bit,一共32bit,其中一位代表正负
unsigned int 无符号位
char(1 byte), short, int, long, long long
float, double
bool(1 byte)
sizeof(x) 查询大小
类型* 指针 类型& 引用
在这里插入图片描述

C++函数

C++头文件

Log.cpp 存放函数
Head files 存放定义的函数签名
在main.cpp中只需要 #include “xxx.h”
“” 相对路径下的文件 <>编译器包含路径,一般调用C++标准库
例如 iosstream 没有.h 这是因为它是C++标准库,C语言的都有.h

C++条件与分支

C++循环

C++控制流语句

continue 直接进行下一次迭代
break 跳出循环
return

C++指针

指针是一个保存内存地址的整数
C++ 提供了两种指针运算符,一种是取地址运算符 &,一种是间接寻址运算符 *。
指针是一个包含了另一个变量地址的变量,您可以把一个包含了另一个变量地址的变量说成是"指向"另一个变量。变量可以是任意的数据类型,包括对象、结构或者指针。

取地址运算符 &

& 是一元运算符,返回操作数的内存地址。例如,如果 var 是一个整型变量,则 &var 是它的地址。该运算符与其他一元运算符具有相同的优先级,在运算时它是从右向左顺序进行的。
您可以把 & 运算符读作"取地址运算符",这意味着,&var 读作"var 的地址"。

间接寻址运算符 *

第二个运算符是间接寻址运算符 ∗ * ,它是& 运算符的补充。 ∗ * 是一元运算符,返回操作数所指定地址的变量的值。

int var = 8;
int* ptr = &var; //&询问内存地址
*ptr = 10 //*给内存地址赋值

C++引用

int var = 8;
int& ref = a; //引用,引用不占用内存地址

指针与引用是内存与数值之间的转化

C++类(面向对象编程)

C语言没有类,但是也可以用,类本质上只是一种grammar sugar,用它来组织代码使代码更容易维护。
class(类)默认是private
public: 可以在类之外的任何地方访问类里的变量
struct(结构体)默认是public

C++中的静态(static)

类或结构体外部使用static 只对定义它的translation unit(.cpp)可见,与类的所有实例共享内存
extern 在translation unit外部找
类或结构体内部使用static
局部静态(local static)在函数中声明局部静态变量的lifetime几乎是整个程序lifetime,scope只有函数本身
Variable lifetime and scope

C++中的枚举(ENUM,enumeration)

有一个数值集合,并且想要数字来表示它们,用枚举
必须是一个整数

enum Example
{
	A, B, C; //默认第一个是0,然后逐渐递增 
};

C++中的构造函数

在创造一个新的实例时运行
设置变量和做初始化
没有初始化的话,参数变量直接指向内存已有的东西,并不是0
当我们构造对象时,直接运行初始化代码——构造函数
对于JAVA等语言,int和float等数据基本类型会自动初始化为0,而C++不会,必须手动初始化所有基本类型

class Entity
{
public:
	float X, Y;
	
	//构造函数
	Entity()
	{
		//默认为空,在这里初始化变量
	}
};

C++中的析构函数

在销毁对象时运行
卸载变量,清理使用过的内存

class Entity
{
public:
	float X, Y;
	
	//析构函数
	~Entity()
	{
		//do something in here
	}
}

C++继承

class Entity
{
};
class Player : public Entity
{
};

C++虚函数

在子类中重写父类的function
如果想要覆写一个function,必须将基类中的基函数标记为虚函数

//基类
virtual std::string Getname() {return "xxx"; }
//子类
std::string Getname() override {return m_Name; }

内存损失:需要一个额外的内存来存储v表,使得可以分配到正确的函数,基类中要有一个成员指针,指向v表
性能损失:每次需要遍历整个v表,来确定要映射到哪个函数

纯虚函数(抽象方法/接口)

允许我们在基类中定义一个没有实现的函数,然后强制子类去实现该函数
纯虚函数必须被实现,才能创建这个类的实例

//基类
virtual std::string Getname() = 0;  //必须在子类中实现,基类无法实例化
//子类
std::string Getname() override {return m_Name; }

C++的可见性

一个面向对象编程的概念,指的是类的某些成员或方法实际上有多可见
三个基础的可见性修饰符
private:(Only*)只有这个类可以访问这些变量 friend
protected:这个类和层次结构中的所有子类,可以访问这个符号
public:所有皆可访问

C++数组

本质上是一个整型指针

int example[5]; //开辟5个int型的内存地址,在栈上创建,运行到大括号结束被destroy

//用new动态分配的内存将一直存在,直到删除它
int* another = new int[5]; //在堆上创建,直到程序把它销毁前都是active
delete[] another;

//C++11
#include <array>
std::array<int, 5> example;
count = example.size();

获取Vector容器的最后一个元素

//方法一: 
return vec.at(vec.size()-1);
 
//方法二: 
return vec.back();
//
方法三: 
return vec.end()-1;  //注意:end指向末尾元素的下一个元素。
 
//方法四: 
return vec.rbegin();

数组操作

vector<int> left; //定义一个空数组
left.push_back(nums[i]); //在数组后面append
left.insert(left.end(), right.begin(), right.end()); //两数组相加
count(left.begin(), left.end(), 'x'); //对x计数
find(left.begin(), left.end(), 'x'); //find() 函数本质上是一个模板函数,用于在指定范围内查找和目标元素值相等的第一个元素。

C++字符串

const char* name = "Hello"; //const can't change the char in string

// string本质上只是一个char数组
#include <string> //不导入的话可以使用但是无法送到cout流中打印到控制台
std::string name = "Hello";
name.size();
name += "world";
name.find("no");

字符串字面量实际上是数组或者指针

const char* name = "Hello"; //指针这个定义是只读状态,不可被修改
char name[] = "Hello"; //定义为数组,可以被修改
name[2] = 'a'; 

C++14
using namespace std::string_literals;
//字符串的append
const char* example = R"(Line1
Line2
Line3)";
const char* example = "Line1"
"Line2"
"Line3";

C++中的const

承诺某些东西是不变的
指针本身 or 指针指向的内容

class Entity
{
private:
	std::string m_Name;
public:
	// 1.const 不允许修改实际的类成员 如m_Name = xxx 不被允许
	// 2.const 承诺不会改变类 如在main中 const Entity e; e.Getname();如果没有这个const会报错
	const std::string& GetName() const
	{
		return m_Name;
	}
};

C++中的mutable关键字

mutable int var; //可以被改变的

类中的const方法可以修改这个成员

C++的成员初始化列表

初始化成员列表和定义的顺序应该相同
多使用

class Entity
{
public:
	float X, Y;

	//构造函数初始化成员列表
	Entity()
		: X(0.0f), Y(1.1f)
	{}
};

int main()
{	
	Entity e;
	std::cout << e.X << ' ' << e.Y << std::endl;
	std::cin.get();
}

C++的三元操作符

if语句的grammar sugar

static int s_Level = 1;
static int s_Speed = 5;

int main()
{
	if (s_Level > 5)
		s_Speed = 10;
	else
		s_Speed = 5;

	s_Speed = s_Level > 5 ? 10 : 5;

	std::string rank = s_Level > 10 ? "Master" : "Beginner";
}

创建并初始化C++对象

选择对象在栈上创建还是在堆上(new keyword)
在堆上分配对栈要花费更多时间,而且在堆上分配必须手动释放被分配的内存(delete)
JAVA所有的东西都在堆上
C#中所有类都在栈上分配

int main()
{
	Entity* e;
	{
		//在栈上分配,{}运行完在内存上销毁
		Entity entity("Hello"); 
		e = &entity; //查看地址
		std::cout << entity.GetName() <<std::endl;
	}
	std::cin.get(); //e = "Unkown"
}
int main()
{
	Entity* e;
	{
		//在堆上分配,new完在内存上delete销毁
		Entity* entity = new Entity("Hello"); 
		e = entity; //查看地址
		std::cout << (*entity).GetName() <<std::endl;
	}
	std::cin.get(); //e = "Hello"
	delete e;
}

C++ new关键字

在堆上不仅分配内存,还调用构造函数
使用new在堆上创建内存,必须使用delete释放内存
placemet new 指定内存地址

int* b = new int[];
delete[] b;

C++隐式转换与explicit关键字

explicit的构造函数,意味着没有隐式的转换

C++运算符及其重载

Vector2 Add(const Vector2& other) const
{
	return Vector2(x + other.x, y + other.y);	
}

Vector2 operator+(const Vector2& other) const
{
	return Add(other);
}

Vector2 Add(const Vector2& other) const
{
	return *this + other;
}

C++的箭头运算符

指针只是一个内存地址,是个数值,不能直接调用方法

int main()
{
	//方法一
	Entity e;
	e.Print();
	//方法二
	Entity* ptr = &e;
	Entity& entity = *ptr;  //必须逆向引用ptr
	entity.Print();
	//方法三
	Entity* ptr = &e;
	ptr->Print(); //->相当于逆向引用,从内存(pointer)中调用方法
}

还可以用于获取内存中某个值的偏移量。

C++的this关键字

访问成员函数(member function)——一个属于某一类的函数或方法,在方法内部可以引用this
this是一个指向当前对象实例的指针,该方法属于这个对象实例

// 场合一:变量与输入变量名一致,无法赋值
class Entity
{
public:
	int x, y;
	
	Entity(int x, int y)
	{
		// Entity* e = this;
		this->x = x;
		this->y = y;
	}
}
// 场合二:在一个类内部调用一个类外部的函数
class Entity
{
public:
	int x, y;
	
	Entity(int x, int y)
	{
		// Entity* e = this;
		this->x = x;
		this->y = y;
		PrintEntity(this);
	}
}

void PrintEntity(Entity* e)
{
	//do something
}

C++的对象生存期(栈作用域生存期)

基于栈的变量在一出作用域的时候就被释放了,摧毁了

C++的智能指针

自动化地在堆上创建内存(new)和释放内存(delete)
实质上是一个原始指针的包装
unique_ptr是作用域指针,在超出作用域时调用delete销毁,不能复制,因为复制后也是指向相同的内存,如果一个死亡,另一个就指向了空内存块
shared_ptr工作方式是引用计数,如果指针的引用变为0,则被销毁
shared_ptr赋值给shared_ptr会增加引用计数,但是赋值给weak_ptr不会增加

#include <memory>
int main()
{
	{
		std::unique_ptr<Entity> entity(new Entity());
		std::unique_ptr<Entity> entity = std::mask_unique<Entity>(); //如果构造函数抛出异常会安全一点

		std::shared_ptr<Entity> sharedEntity = std::mask_unique<Entity>();
	}
}

C++的复制与拷贝构造函数

strcpy includes the null termination character;

memcpy(m_Buffer, string, m_size); //复制字符串

拷贝构造函数,C++会有个默认的拷贝构造函数,做的是内存复制,将other对象的内存浅层拷贝进成员变量
浅拷贝:不会去到指针的内容或者指针指向的地方,只是复制指针,所以复制出来的指向同一内存
深拷贝:复制整个对象,不仅复制指针,也复制指针所指向的内存

String(const String& other)
	:m_Size(other.m_Size)
{
	m_Buffer = new char[m_Size + 1];
	memcpy(m_Buffer, other.m_Buffer, m_size+1); 
}

总是通过 const引用传递对象

C++动态数组

Vector - ArrayList
创建可以没有固定大小

#include <vector>

std::vector<int> list;
list.push_back(0); // Python append 在main下创建,复制进vector
list.push_back(1);
for(int i = 0; i < list.size(); i++)
	std::cout << list[i] <<std::endl;
for(int& v : list)
	std::cout << v <<std::endl;

list.clear(); //清除数组
list.erase(list.begin() + 1); //删除数组某一位

stdvector使用优化

push_back 复制旧的,然后重新分配,慢

list.reserve(3); //扩展vector
list.emplace_back(0); // 直接在vector中创建

C++中使用库(静态链接与动态链接)

OpenGL第三方库:GLFW glfw3.dll、glfw3.lib、glfw3.dll.lib
静态链接和动态链接的主要区别是库文件是否被编译到exe文件或链接到exe文件中
静态链接:这个库会放在可执行文件(.exe)中,没有外部依赖 glfw3.lib

#include <GLFW/glfw3.h>

int a = glfwInit();

动态链接:动态链接库是在运行时被链接的,可以选择在程序运行时,装载动态链接库,有外部依赖 glfw3.dll glfw3.dll.lib

引用第三方库用< >:外部的库,不在VS中和解决方案一起编译
引用第三方库用" " :会先检查相对路径,在实际解决方案中

C++中创建与使用库

C++如何处理多返回值

Array会在栈上创建,而Vector会把它的底层存储存储在堆上,所以返回std::array会更快
tuple, pair

//用结构体做
struct result
{
	std::string str;
	int val;	
};

C++的模板

模板并不是实际存在的,直到我们调用它

#include <iostream>
#include <string>

template<typename T> // 可以输出各种类型的value
void Print(T value)
{
	std::cout << value <<std::endl;
}

template<Typename T, int N> // 在栈上生成指定类型和大小的array
class Array
{
private:
	T m_Array[N];
};
Array<int, 5> array;

C++的堆与栈内存比较

int main()
{
	int value = 5; //在栈上分配内存

	int* hvalue = new int; //在堆上分配内存,new关键字分配内存
	*hvalue = 5;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/378529.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WebRTC Qos策略

1.WebRTC 用于提升 QoS 的方法&#xff1a;NACK、FEC、SVC、JitterBuffer、IDR Request、PACER、Sender Side BWE、VFR&#xff08;动态帧率调整策略&#xff09;https://blog.csdn.net/CrystalShaw/article/details/80432267丢包重传NACK&#xff1a;一种通知技术&#xff0c;…

【办公类-19-02】Python批量制作word文本框的名字小标签,用A4word打印(植物角、家长会、值日生)

背景需求&#xff1a; 2月28日去小班带班&#xff0c;看到班主任制作了一些小手印花束作为家长会的家长座位提示&#xff0c;上面贴着“”圆形白色的幼儿名字贴”。 我立刻想起了制作的过程——在word中插入文本框&#xff0c;然后复制无数个文本框&#xff0c;摆好位置&#…

Win11的两个实用技巧系列之设置系统还原点的方法、安全启动状态开启方法

Win11如何设置系统还原点?Win11设置系统还原点的方法很多用户下载安装win11后应该如何创建还原点呢&#xff1f;现在我通过这篇文章给大家介绍一下Win11如何设置系统还原点&#xff1f;在Windows系统中有一个系统还原功能可以帮助我们在电脑出现问题的时候还原到设置的时间上&…

spring循环依赖debug源码【Java面试第三季】

spring循环依赖debug源码【Java面试第三季】前言spring循环依赖debug源码35_spring循环依赖debug源码01全部Debug断点36_spring循环依赖debug源码0237_spring循环依赖debug源码0338_spring循环依赖debug源码04最后前言 本文是4.Spring【Java面试第三季】的小节 spring循环依赖…

守护进程与TCP通讯

目录 一.守护进程 1.1进程组与会画 1.2守护进程 二.创建守护进程 setsid函数&#xff1a; 三. TCP通讯流程 3.1三次握手&#xff1a; 3.2 数据传输的过程 3.3四次挥手 一.守护进程 1.1进程组与会画 进程组&#xff1a;进程组由一个进程或者多个进程组成&#xff0c;每…

谷歌优化排名怎么做出来的?谷歌排名多久做上去?

本文主要分享谷歌排名的算法机制&#xff0c;让你很容易地用更短的时间把Google的自然排名做到首页。 本文由光算创作&#xff0c;有可能会被剽窃和修改&#xff0c;我们佛系对待这种行为吧。 谷歌优化排名怎么做出来的&#xff1f; 答案是&#xff1a;持续更新原创优质内容…

让WPF中的DataGrid像Excel一样可以筛选

在默认情况下&#xff0c;WPF提供的DataGrid仅拥有数据展示等简单功能&#xff0c;如果要实现像Excel一样复杂的筛选过滤功能&#xff0c;则相对比较麻烦。本文以一个简单的小例子&#xff0c;简述如何通过WPF实话DataGrid的筛选功能&#xff0c;仅供学习分享使用&#xff0c;如…

唯品会财报:一面骄阳,一面寒霜

配图来自Canva可画 在互联网技术飞速发展、物流基础设施日益完善&#xff0c;以及消费者购物习惯不断改变等多重因素的共同影响下&#xff0c;电商行业实现了蓬勃发展。得益于此&#xff0c;电商行业也跑出了许多知名电商品牌&#xff0c;其中既有淘宝、京东、拼多多等综合型电…

SSRF漏洞原理、危害以及防御与修复

一、SSRF漏洞原理漏洞概述SSRF&#xff08;Server-side Request Forge&#xff0c;服务端请求伪造&#xff09;是一种由攻击者构造形成由服务端发起请求的安全漏洞。一般情况下&#xff0c;SSRF攻击的目标是从外网无法访问的内部系统。正是因为它是由服务端发起的&#xff0c;所…

Java开发 - Elasticsearch初体验

目录 前言 什么是es&#xff1f; 为什么要使用es&#xff1f; es查询的原理&#xff1f; es需要准备什么&#xff1f; es基本用法 创建工程 添加依赖 创建操作es的文件 使用ik分词插件 Spring Data 项目中引入Spring Data 添加依赖 添加配置 创建操作es的业务逻…

深度学习常用的激活函数总结

各种激活函数总结 目录一、sigmoid二、tanh![在这里插入图片描述](https://img-blog.csdnimg.cn/a0d92552edf8464db793fdd2f2b75cb5.png)三、ReLU系列1.原始ReLU2.ReLU改进&#xff1a;Leaky ReLU四、swish五、GeLU一、sigmoid 优点&#xff1a; 1.可以将任意范围的输出映射到 …

高通平台开发系列讲解(Sensor篇)AlsPs的工作原理及介绍

文章目录 一、什么是ALS?二、什么是距感(PS)?三、AlsPs的工作原理四、AlsPs的特性五、距感的校准参数说明六、光感的校准参数说明沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇文章将介绍 AlsPs 的工作原理及介绍。 一、什么是ALS? 光感的英文叫做Ambient Li…

算法小抄2-刷题中Python的常用语法

标准数据类型 不可变数据类型: Number String Tuple 可变数据类型:List Dictionary Set 关于为什么会分成可变和不可变最后会讲到哦 Number Number支持int,float,bool,complex四种,其中int范围小且必须为整数,float范围较大,可以是是小数,bool值表示是否,complex为复数,赋值…

20- widedeep及函数式构建模型 (TensorFlow系列) (深度学习)

知识要点 wide&deep: 模型构建中, 卷积后数据和原始数据结合进行输出.fetch_california_housing&#xff1a;加利福尼亚的房价数据&#xff0c;总计20640个样本&#xff0c;每个样本8个属性表示&#xff0c;以及房价作为target&#xff0c;所有属性值均为number&#xff0…

网上医疗预约挂号系统

技术&#xff1a;Java、JSP等摘要&#xff1a;网上医疗预约挂号系统是主要是对居民的保健、护理、疾病预防等健康信息实行有效的预约挂号管理。医疗机构为居民建立完整的健康档案&#xff0c;安排体检以及实施免疫等预防措施。而基于Web的远程保健平台以网上医疗预约挂号系统为…

基于OMAPL138+FPGA核心板多核软件开发组件MCSDK开发入门(上)

本文测试板卡为创龙科技 SOM-TL138F 是一款基于 TI OMAP-L138(定点/浮点 DSP C674x + ARM9)+ 紫光同创 Logos/Xilinx Spartan-6 低功耗 FPGA 处理器设计的工业级核心板。核心板内部OMAP-L138 与 Logos/Spartan-6 通过 uPP、EMIFA、I2C 通信总线连接,并通过工业级 B2B连接器引…

分布式任务处理

分布式任务处理 1. 什么是分布式任务调度 视频上传成功需要对视频的格式进行处理&#xff0c;如何用Java程序对视频进行处理呢&#xff1f;这里有一个关键的需求就是当视频比较多的时候我们如何可以高效处理。 如何去高效处理一批任务呢&#xff1f; 1、多线程 多线程是充…

IDEA社区版环境配置和插件安装

一、Java环境安装 1.1 下载openjdk环境安装包 可以进华为镜像站进行下载。参考链接&#xff1a; Index of openjdk-local https://repo.huaweicloud.com/openjdk/ 1.2 配置Java环境 解压缩openjdk到任意路径&#xff0c;建议路径不要有中文。然后把路径的bin文件&#xff0…

新手小白亚马逊注册最全教程在此

自从龙哥出了Walmart注册教程后&#xff0c;立刻看到私信有兄弟问这个亚马逊的注册。亚马逊是跨境电商的鼻祖&#xff0c;资源和流量是无容置疑的。作为一个重产品&#xff0c;轻店铺的平台&#xff0c;是比较看中客户体验的&#xff0c;要求卖家要有好的资源。而且亚马逊有强大…

02-MyBatis查询-

文章目录Mybatis CRUD练习1&#xff0c;配置文件实现CRUD1.1 环境准备Debug01: 别名mybatisx报错1.2 查询所有数据1.2.1 编写接口方法1.2.2 编写SQL语句1.2.3 编写测试方法1.2.4 起别名解决上述问题1.2.5 使用resultMap解决上述问题1.2.6 小结1.3 查询详情1.3.1 编写接口方法1.…