滴水三期:day42.1-面向对象编程及this指针说明

滴水逆向——C++_this指针 1、直接使用结构体做为参数\传递结构体指针 2、空结构体的大小为1 3、函数可以放在结构体里面,也可以放在结构体外面 struct sclass { int a; int b; int c; int d; int Plus(sclass* sc) { return sc->a + sc->b; ... 阅读详情

一、面向对象编程

笔者由于学习过JAVA,所以对面向对象编程已经有一些自己的理解,下面不会讲解太详细

1.结构体<=>类

  • 先复习一下结构体作为参数传递:结构体作为参数传给函数,本质上是将结构体中所有成员复制一份传到函数的栈中。这样会比较浪费空间和时间

  • 所以我们会将结构体指针作为参数传递给函数:

    #include "stdafx.h"
    struct Base{
        int x;
        int y;
    };
    int Max(Base* basep){  //结构体指针传参
        return basep->x + basep->y;
    }
    int main(int argc,char* argv[]){
        Base base;
        base.x = 1;
        base.y = 2;
      	printf("%d\n",Max(&base));
        printf("%d",sizeof(base));  //打印一下结构体的大小
        return 0;
    }
    
  • 这里我们查看一下现在结构体的大小:8字节。现在如果把Max函数放到Base结构体中,再看看是否报错,并且查看此时结构体的大小:

    #include "stdafx.h"
    struct Base{
        int x;
        int y;
    	int Max(Base* basep){   //把Max函数放到Base结构体中
    		return basep->x + basep->y;
    	}
    };
    int main(int argc,char* argv[]){
        Base base;
        base.x = 1;
        base.y = 2;
      	printf("%d\n",base.Max(&base));  //这里调用函数时就需要用“结构体变量.”的方式调用
        printf("%d",sizeof(base));  //打印一下结构体的大小
        return 0;
    }
    
    • 函数作用范围受限:会发现完全可以把函数定义到结构体当中,但是在调用这个函数时需要把函数当成结构体中成员来调用:即base.Max()的方式来调用!
    • 结构体中函数不影响结构体大小:且发现结构体大小还是8字节!即Max函数当做结构体成员使用,但是却不包含在结构体当中
  • 综上:可以发现和面向对象的编程语言很像!结构体就是类,结构体中的变量就是成员变量,结构体中的函数就是成员方法,使用Base base可以创建类的对象base,使用对象可以调用类中的变量和方法等,这些就是封装的思想

2.成员方法的参数传递

  • 见上述例子中:base.Max(&base),调用Base类中的方法,查看一下反汇编:发现虽然Max方法只有一个参数,但是却传入了两个参数!我们来分析一下:①lea eax,[ebp-8]和push eax,这两个语句就是把base结构体变量的首地址使用栈的方式传递给了Max函数;②lea ecx,[ebp-8],这条语句就是把base结构体变量的首地址以寄存器传参的方式传递给了函数(因为进入进入函数中发现ecx中的值最终是被存储到了函数的栈中ebp-4的位置)

    175249 180031

  • 思考:为什么明明只应该有&base这一个参数,但是编译器又自动传递了一个结构体变量首地址给函数?所以我们大胆尝试一下:如果在结构体中定义一个无参数的成员函数,编译器会怎么做呢?

    #include "stdafx.h"
    struct Base{
        int x;
        int y;
    	int Max(){
    		return x + y;
    	}
    };
    int main(int argc,char* argv[]){
        Base base;
        base.x = 1;
        base.y = 2;
      	printf("%d\n",base.Max());  //3
        return 0;
    }
    

    使用反汇编再查看一下:发现即使类中的方法没有设置参数,编译器还是会自动把所属结构体变量的首地址作为参数传递给函数;而且即使函数中没有指明x,y是哪里来的,但是编译器会根据传入的结构体变量首地址去找结构体当中的x和y

    180945 181700

  • 综上:编译器调用类中的成员方法时,会自动传递一个参数,且这个参数就是此结构体变量的首地址,我们把这个指针类型变量就叫做==this指针==

  • 所以和C语言相比如果按照C++的语法格式和思想方法,定义类、成员变量、成员方法等,编译器会帮我们添加很多额外的功能,节省很多时间,代码编写也会便利很多。我们需要学的就是使用C++时,编译器帮我们做了哪些事情,使开发效率更高更便捷

3.this指针的使用

  • 既然this指针指向的是当前结构体变量的首地址,那么我们就可以按照最开始&base的使用方式使用this指针,比如:

    #include "stdafx.h"
    struct Base{
        int x;
        int y;
    	int Add(){
    		return this->x + this->y;  //this->
    	}
    };
    int main(int argc,char* argv[]){
        Base base;
        base.x = 1;
        base.y = 2;
      	printf("%d\n",base.Add());
        return 0;
    }
    

    使用结构体指针的方式使用类中的成员:this->x,但是这样做好像有点多余,那么this指针什么时候用呢?

  • 当成员方法的参数和所在类中的成员变量同名时,使用this来区分这个变量是成员变量

    #include "stdafx.h"
    struct Base{
        int x;
        int y;
    	void Init(int x,int y){  //定义初始化成员变量的方法
    		this->x = x;
            this->y = y;
    	}
    };
    int main(int argc,char* argv[]){
        Base base;
      	base.Init(1,2);  //直接使用Init方法对成员变量赋值
        return 0;
    }
    

    this->x = x就区分了左边的x是成员变量,右边是传进来的参数,即将传进来的参数x的值赋给成员变量x

  • 还可以使用this指针,返回当前结构体变量的首地址

    #include "stdafx.h"
    struct Base{
        int x;
        int y;
    	int getAddress(){
    		return *((int*)this);  //返回当前结构体变量首地址
    	}
    };
    int main(int argc,char* argv[]){
        Base base;
      	base.getAddress();
        return 0;
    }
    

    因为this指针指向当前结构体变量的首地址,即==指向当前对象的首地址==,且this是一个结构体*类型的变量,所以要将当前对象的首地址以int类型返回,就需要先把Base*转成int*,再加一个*,把这个地址值取出来

  • 注意:前面C语言学过的各种指针类型变量都可以做++,–,+/-一个数,比较等操作,但是this指针不允许重新赋值!

4.成员方法压栈顺序和堆栈平衡

  • 编写一个普通函数和类的成员方法,分别调用这两个函数比较区别:

    #include "stdafx.h"
    struct Base{
        int x;
        int y;
    	void Init(int x,int y){  //定义成员方法
    		this->x = x;
            this->y = y;
    	}
    };
    int method(int x,int y){  //定义函数
    	return x + y;
    }
    int main(int argc,char* argv[]){
        Base base;
      	base.Init(1,2);
    	method(1,2);
        return 0;
    }
    
  • 通过反汇编发现:

    • 一般函数采用栈传递参数,参数从右到左压栈,使用外平栈(即cdecl调用约定);

    • 成员方法参数采用栈传递参数,参数从右到左压栈,但是使用内平栈,且this指针参数最后一个传递,并采用寄存器的方式传递给函数(thiscall调用约定)

      image-20230422191952689

二、作业

1.设计一个类

  • 要求设计一个类,有两个Int类型的成员x,y,并在类内部定义4个函数分别实现对x,y的加法、减法、乘法与除法的功能

    #include "stdafx.h"
    struct Calculator{
        int x;
        int y;
    	void Init(int x,int y){
    		this->x = x;
    		this->y = y;
    	}
    	int add(){
    		return this->x + this->y;
    	}
    	int sub(){
    		return x - y;
    	}
    	int mul(){
    		return x * y;
    	}
    	int div(){
    		return this->x / this->y;
    	}
    };
    int main(int argc,char* argv[]){
        Calculator cal;
    	cal.Init(4,2);
    	printf("%d %d %d %d",cal.add(),cal.sub(),cal.mul(),cal.div());
        return 0;
    }
    

2.空结构体

  • 定义一个空结构体,查看其大小

    #include "stdafx.h"
    struct Nothing{	
    };
    int main(int argc,char* argv[]){
    	Nothing nothing;
    	Nothing nothing1;
    	Nothing nothing2;
    	int size = sizeof(nothing);
    	printf("%X %X %X",&nothing,&nothing1,&nothing2);
    	printf("%d",size);
        return 0;
    }
    
    • 会发现空结构体的大小为1字节。而且通过反汇编发现,这个1字节直接是编译器直接赋上去的!

      image-20230422195946089
    • 而且就算是空的类(结构体),也可以生成对象!说明编译器肯定会给一个空结构体对象至少给1字节空间,否则如果空结构体真是空的,编译器凭什么还会给结构体对象分配内存空间。

    • 通过反汇编可以发现:定义的三个类的对象,但是对象所在地址都不一样!第一个nothing对象首地址为ebp-4;第二个nothing1对象首地址为ebp -8;第三个nothing2对象首地址为ebp-0xC

      200128

3.空指针调用成员方法

  • 判断下面两个代码能否正常执行,并说明理由

  • 下面代码中:定义了一个空指针p,接着又用这个空指针p调用的成员函数,C++中是允许空指针调用成员函数的,那么p->Fn_1();到底是什么意思呢?

    • 我们知道当程序编译完成后,Person类中的成员函数Fn_1()和Fn_2()的地址就已经确定了(因为此类所有的对象都共用一个成员函数!可以理解为一个全局变量的感觉),所以**p->Fn_1(),就是相当于执行Person::Fn_1(this);,且把this指向空**,而此时Fn_1()中并没有使用到this!所以this空不空无所谓!Fn_1还是可以正常执行
    • Fn_2同理
    #include "stdafx.h"
    struct Person{  		
        void Fn_1(){	
    		printf("Person:Fn_1()\n");
    	}	
        void Fn_2(){	
    		printf("Person:Fn_2()%x\n");
    	}	
    };  				
    int main(int argc, char* argv[]){				
    	Person* p = NULL;
    	p->Fn_1();	
    	p->Fn_2();		
    	return 0;	
    }
    
  • 而下面的代码:Fn_1()中同样还是没有使用this指针,所以按照上述理由,还是可以正常执行;但是Fn_2()中,x = 10相当于this->x = 10,这里由于this指向空,但是又用空指针->x,而空指针的地址是0x00000000,->x的本质前面学过,就是从0x00000000开始向后取4字节的值,这个地址是非法访问的,所以会报错!(或者直接理解成不能使用空指针即可)

    #include "stdafx.h"
    struct Person{  		
    	int x;	
        void Fn_1(){	
    		printf("Person:Fn_1()\n");
    	}	
        void Fn_2(){	
    		x = 10;   //这里相当于this->x = 10;
    		printf("Person:Fn_2()%x\n");
    	}	
    }; 				
    int main(int argc, char* argv[]){		
    	Person* p = NULL;		
    	p->Fn_1();	
    	p->Fn_2();		
    	return 0;	
    }
    
  • 那我们把代码改一下:把person对象地址赋给结构体类型的p指针,再用p指针调用成员方法,此时p->Fn_2(),就相当于调用Fn_2()成员方法,并且将this指针指向person对象,此时就可以正常执行this.x = 10了

    #include "stdafx.h"
    struct Person{  		
    	int x;	
        void Fn_1(){	
    		printf("Person:Fn_1()\n");
    	}	
        void Fn_2(){	
    		x = 10;
    		printf("Person:Fn_2()%x\n");
    	}	
    };  		 				
    int main(int argc, char* argv[]){		
    	Person* p = NULL;		
    	p->Fn_1();
    	
        Person person;
    	person.Fn_2();  //这是正常用对象调成员函数
    	
        p = &person; //把person对象地址赋给结构体类型的p指针
    	p->Fn_2(); //此时p->Fn_2(),就相当于调用Fn_2()成员方法,并且将this指针指向person对象
    	
        return 0;	
    }
    
二、 类和对象 其实就是对象里边如果还有对象,浅拷贝之后,被拷贝的对象里边的这个对象只是个引用。在main()函数调用foo()之前,会在自己的栈帧中开辟一个临时空间,该空间的地址作为隐藏参数传递给foo()函数,在需要返回A对象的时候,就在这个临时空间上构造一个A a。浅拷贝 如果当数组或对象中的值是`基本类型数据`,那拷贝后的数据和原数据是完全没有关联,且互不影响的两个数据, 如果数组或对象的值是`引用类型数据`的话,拷贝后的数组或对象中的引用类型的值跟原数据中的引用类型的值,还是会保持共同的内存地。 阅读详情

相关推荐

四类九种移位寄存器总结(循环(左、右、双向)移位寄存器、逻辑和算术移位寄存器、串并转换移位寄存器、线性反馈移位寄存器LFSR|verilog代码|Testbench|仿真结果)

移位寄存器有哪些分类呢? 按移位方向分类:①单向移位寄存器(包括左移、右移)②双向移位寄存器 按循环方式分类:①循环移位寄存器②非循环移位寄存器 按部位的不同分类:①逻辑移位寄存器②算术移位寄存器 按输入输出方式分类:①串入串出②串入并出③并入串出④并入并出

Loudrs的博客 1万+

滴水逆向三期笔记和作业-c++总结1

this指针,继承 构造-析构函数,权限控制

weixin_44449397的博客 1930

深入解析JESD204B Periodic SYSREF在多ADC/DAC系统中的同步优化策略

本文深入探讨了JESD204B Periodic SYSREF在多ADC/DAC系统中的同步优化策略,针对雷达阵列和宽带通信系统中的同步精度问题,详细解析了硬件实现细节、参数配置实战经验及系统级优化方法。通过案例分析和技术要点,帮助工程师解决由温度漂移和时钟抖动引起的同步挑战,提升系统性能。

weixin_29267307的博客 137

深挖C++:类和对象(中)

(先进后出)

xys_678的博客 246

PID控制参数整定(调节方法)原理+图示+MATLAB调试

序 首先最重要的是了解每个参数调节了系统响应的那些属性,通过观察响应从而调节参数改变属性。 PID的作用概述: 1、P产生响应速度和力度,过小响应慢,过大会产生振荡,是I和D的基础。 2、I在有系统误差和外力作用时消除偏差、提高精度,同时也会增加响应速度,产生过冲,过大会产生振荡。 3、D抑制过冲和振荡,过小系统会过冲,过大会减慢响应速度。D的另外一个作用是抵抗外界的突发干扰,阻止系统的突变。 同时调节的顺序是:P>I>D 下面了解的一个很重要的就是调节的目标,也就是最好的响应曲线.

viafcccy的博客 16万+

【可信数据空间-连接器技术架构设计方案】

一句话概括连接器是可信数据空间的“数据保镖”和“外交官”。连接器就是一个部署在你本地的软件代理,它代表你安全地对外提供数据服务,确保在共享数据价值的同时,牢牢守住数据的所有权和控制权。它是实现“数据可用不可见”这一理想的关键技术部件。一个生动的比喻:银行的金库和接待员想象一下,你的数据就是藏在银行金库里的黄金和钞票。金库(你的内部数据库): 绝对安全,外人绝对不能进。接待员(连接器): 坐在银行大厅里,负责与客户打交道。客户向接待员提出请求:“我想取1000元。

u014716614的博客 2270

C++移动构造函数详解

移动构造函数是C++11引入的一种特殊构造函数,用于从临时对象(右值)"窃取"资源来初始化新对象,而不是进行昂贵的深拷贝。char* data;public:// 移动构造函数:参数是右值引用 &&// 关键:把源对象的资源置空。

拒绝AI文,努力在AI时代写出感动人心的好文章 392

海上AI导航系统:技术架构与行业应用解析

计算机视觉与强化学习技术在海上导航系统中的应用正逐步改变传统航运业。通过多模态传感器融合技术,现代AI导航系统能够实现高精度的物体识别与实时路径规划,有效解决能见度依赖、决策延迟等核心痛点。以Orca AI的SeaPod系统为例,其结合了NVIDIA GeForce RTX 4070的边缘计算能力与多光谱协同识别技术,在恶劣环境下仍能保持稳定性能。这类系统不仅提升了航行安全性,还通过优化航线显著降低燃油消耗,在东京湾、马六甲海峡等繁忙水域展现出巨大价值。随着毫米波雷达融合方案的测试推进,未来海上导航将突破极

weixin_33597080的博客 354

ThunderKittens 深度解析:一个不基于 MLIR 的 C++ 模板 GPU DSL

Triton 是"让更多人能写 GPU kernel",ThunderKittens 是"让会写的人写得更爽"。前者用 MLIR 换易用性,后者用 C++ 模板换可控性。它们不是替代关系,而是覆盖了 GPU 编程光谱的两端。ThunderKittens 的出现,本质上是对"GPU DSL 必须基于 MLIR"这一默认假设的挑战。编译期类型系统本身就可以是一个强大的 DSL 基础设施,不需要中间 IR,不需要黑盒 pass,也能实现 tile 级抽象和零运行时开销。

Maxwell_Newton的博客 344

Claude Code+Cursor+Claude 4三剑合璧!5步搞定Magentic-UI的OAuth2.0集成,开发效率飙升500%,新手秒变全栈工程师

本文详细介绍了如何利用Claude Code、Cursor和Claude 4三款AI工具高效集成Magentic-UI的OAuth2.0认证系统。通过5个步骤的实战演练,开发者可快速完成从环境搭建、项目分析、代码生成到前端集成的全过程,显著提升开发效率。文章还提供了JWT令牌管理、安全配置及常见问题解决方案。

weixin_29234509的博客 453

以太网以及车载以太网概述

千兆网线和百兆网线区别 1、所谓的百兆网线其实就是 五类线 和超五类线 ,而千兆网线主要是指六类线 和超六类线 ,另外还有古老的十兆网线也就是指 四类线 和 三类线 等。 2、在使用上,其实千兆网线和百兆网线是没什么区别的,千兆网线完全兼容百兆网络。 3、百兆网线的线芯是8芯,但上传和下载只用到了其中的4根,而千兆网线需要完全用到8根。 4、另外在线芯的排布上,千兆网线的线芯中间有个十字形的塑料架,用来把四组8芯的线分开,这个百兆网线是没有的, 5、所有的网线在外皮上都有种类标识,CAT5 CAT

$好记性还是要多记录$ 4074

跟我学c++中级篇—类型定义的方式

本文系统阐述了编程中类型定义的重要性及c++中的实现方式。重点对比了宏定义、typedef与modern using三种机制,指出using在可读性、灵活性和模板支持上的优势,推荐优先使用。同时提醒开发者注意别名滥用、类型歧义、错误信息冗长等问题,强调统一规范与合理设计。最终结论:在现代c++开发中,应以using为主,兼顾简洁性与可维护性,避免陷入命名混乱与编译困境。

fpcc的专栏 84

Xiaojie雷达之路---手把手教你从串口获取雷达原始数据(一)---新建工程(开始)

Hello,大家好,我是Xiaojie,欢迎大家能够和Xiaojie来一起学习毫米波雷达知识,Xiaojie准备连载一个系列的文章---利用串口获取毫米波雷达中的原始数据,本系列文章将从新建工程到最后原始数据显示到PC上进行逐步介绍,这个系列的文章大约是一个4-5篇左右。本篇文章呢,主要讲的是如何新建一个毫米波雷达的工程。

XiaoJie的博客 5810

【C语言】字符与字符串函数

C语言中字符串为以\0结尾的字符数组,标准库函数基于此约定。本文解析字符串内存布局,详解ctype.h与string.h中字符分类、长度计算、拷贝、比较等函数的使用要点,强调长度判断与越界风险,最后通过命令行待办事项示例整合fgets、sscanf、strncpy、strcmp,展示实际应用中的关键细节。

记录在学习过程中学到的知识 352

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

C++ 函数模版

模板参数:● template ,T 就是类型占位符,名字可以自定义,习惯用T● 占位符可以在函数返回值、形参、函数内部当作类型使用使用要点模板代码一般写在头文件:编译器需要看到完整模板源码,才能在每个编译单元完成实例化全局函数、类内成员函数都可以写成模板实例化发生在编译阶段,不是运行时隐式实例化:调用时编译器自动推导实参类型,生成对应版本函数。

2501_94041724的博客 306

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

#SQLite 数据库笔记一:(概念 / 终端指令 / SQL 语句 / C 编程 / 回调函数)

数据库 = 数据的仓库,假设数据是海量。能力说明存储数据持久化保存,程序退出数据还在统计数据、分组、排序数据管理增、删、改、查(CRUD)嵌入式设备上也会用数据库(单片机网关、路由器、工业 HMI 都常见),因为 sqlite 体积小、无需服务进程、单文件即可。数据库 = 库 > 表 > 记录(行) > 字段(列)sqlite3 = 开源、C 写的、单文件、免安装、最多 2T 的嵌入式关系型数据库。

lwq20051110的博客 217

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【C++ 基础入门】C++继承(下):问题、底层原理与组合

C++继承(菱形继承的问题、虚继承原理、继承与组合、构造顺序)

2601_96587588的博客 795

蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级 备考:莫队算法离线区间查询详解

备赛进行时:第十八届蓝桥杯软件赛报名已于 2026-10-08 10:00 开启、12-18 14:00 截止,省赛定在 2027-04-10(C/C++·Python 程序设计 9:00–13:00);中国电子学会 2026 年 12 月软件编程(C/C++ 一级至十级、Python 一级至六级)考级报名 9/23–12/2 16:00、统考 12-12;全国青少年信息素养大赛 2026—2027 赛季算法应用主题赛也已进入复盘练兵窗口。

IT_Scratch的博客 158

825 mW 顶上 212 °C:ASM491S 的 105 °C/W、250 mA 短路电流与热关断

25 °C 环境里结温 34.1 °C,125 °C 环境里结温 134.1 °C——后者已经离 150 °C 只有 16 °C 了,但还在范围内。换个角度看同一件事:从 25 °C 和从 125 °C 起算,温升都是 86.6 °C,但一个到 111.6 °C(还在范围内),一个到 211.6 °C(远远超限)。这个算例里 20 °C/W 是我假设的,实际值取决于机壳材料、密封程度、有没有风扇,跨度可以从 5 °C/W 到 50 °C/W 以上。外面 50 °C 的机箱,盒内就是 63.9 °C。

ANSILIC的博客 361

《C++ 项目:手写大模型接入 SDK》Gemini接口设计(上):初始化、全量响应实现和测试

本文系统完成了Gemini模型通过OpenAI兼容API的接入开发,基于Apifox验证接口规范,设计并实现GeminiProvider类,涵盖初始化、状态检测、全量响应等核心功能。重点处理了代理配置强制校验、Bearer鉴权、JSON序列化与响应解析等工程细节,并通过GTest与CMake完成单元测试,验证链路可用性。项目遵循策略模式,保持与DeepSeek、ChatGPT等模型的统一抽象接口,显著提升SDK可扩展性。

2501_91275995的博客 393

【容斥原理计数】题解:P9489 ZHY的表示法_容斥原理_计数问题_前缀和问题转化_算法竞赛C++

给定 $ n $ 个正整数,求区间 $[l,r]$ 中有多少正整数 $ x $ 可表示为 $ \sum \lfloor \frac{y}{x_i} \rfloor $。通过二分确定最大 $ y $,转化为求 $ 1 \sim H $ 中是某些 $ x_i $ 倍数的数的个数,利用容斥原理与 DFS 枚举子集计算,结合 LCM 预判剪枝及去重优化,时间复杂度 $ O(2^n \log V) $,可高效处理 $ r \le 10^9 $ 的数据。

YLCHUP的博客 42

头歌 数据结构——C&C++线性表实训

本系列任务围绕线性表的链式实现,依次完成顺序构建、逆序构建、排序插入、查找、删除、求长度及栈、队列、集合等应用。通过动态内存分配与指针操作,掌握单链表的基本操作与实际应用,涵盖插入、删除、遍历、搜索等核心功能,最终实现数据结构在典型场景中的灵活运用。

一名敲代码的苦13程序员 240

C++ vector 添加与删除元素的底层原理:erase 返回值与倒序遍历删除

vector是连续内存的动态数组,支持O(1)随机访问,但扩容时需重新分配内存并搬迁元素。push_back和emplace_back均摊时间复杂度为O(1),扩容策略(如2倍或1.5倍)确保总代价均摊;insert与erase在中间位置操作需移动元素,时间复杂度O(n),且使后续迭代器失效。删除指定元素推荐使用erase-remove惯用法或std::erase_if,避免逐个删除导致O(n²)复杂度。从后往前遍历可防止漏删,但最优解仍是高效惯用法。预估容量后调用reserve()可避免频繁扩容,提升性能

2402_85743155的博客 798

字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)

本题核心思想是:最少移动步数 = 总长度 - 可保留的最长连续子串长度。未移动字母在T中必须为连续子串,在S中需保持相对顺序(即子序列)。通过枚举T的所有连续子串起点,贪心匹配S中的对应字符,求出最长可保留长度L,答案即为n−L。时间复杂度O(n²),空间复杂度O(n),适用于n≤1000。

冻柠茶飞冰走茶 588

【C语言】内存函数

本文介绍C语言中按字节操作的内存函数(memcpy、memmove、memset、memcmp、memchr),强调其长度参数以字节为单位,适用于二进制数据。重点解析memcpy不允许重叠的原因及memmove通过判断相对位置选择复制方向来安全处理重叠场景,并结合动态数组的插入与删除操作,展示memmove的实际应用。

记录在学习过程中学到的知识 329

C++ 标准库算法全景指南

本文系统梳理C++标准库<algorithm>与<numeric>中100+算法,按功能分为非修改、修改、排序、二分查找、归并、堆、极值、字典序、排列及数值操作十大类,涵盖典型用法与时间复杂度。结合C++20范围(ranges)与投影特性,实现更简洁高效的代码。

sss123ddd的博客 360
上一篇: 滴水三期:day41.2-PE阶段所有代码汇总(PE文件分析器基本C代码)
下一篇: 滴水三期:day43.1-构造、析构函数和继承
EdimadeZhou
博客等级 码龄5年 241粉丝 128原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值