C++入门(有C语言基础)
string类
- string类初始化的方式大概有以下几种:
string str1;string str2 = "hello str2";string str3("hello str3");string str4(5, 'B');string str5[3] = {"Xiaomi", "BYD", "XPeng"};string str6 = str5[2];str1 = "nihao str1";
- 通过
size()或length()函数可以获取字符串的长度:
// 获取长度,不会包含'\0'cout << str1.size() << endl;cout << str1.length() << endl;cout << str4.size() << endl;cout << str5[0].size() << endl;
- 两种访问字符的方式:通过
[]运算符或at()方法来访问字符串中的某个字符。at()具有边界检查,如果访问越界会抛出异常,而[]不会做边界检查。[]导致的越界会产生未定义行为,越界后会访问到其他地址,系统不会报错;at()只要一越界就要抛出错误,程序终止。一个string占32个字节。
cout << str2[7] << endl;cout << str2.at(7) << endl;cout << str5[0][2] << endl;cout << str5[0].at(2) << endl;
- 拼接字符串:
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{string str1 = "成长是永远";string str2 = "离别是空悬";cout << str1 + str2 << endl;return 0;
}
- 比较字符串:可以直接使用
==,!=,<,>,<=,>=来比较两个字符串的字典顺序。对应ASCII码值大的就大,逻辑表达式为真返回1,为假返回0.
string str1 = "abc";string str2 = "xyz";cout << (str1 <= str2) << endl;
- 子字符串提取:
substr()函数用于提取子字符串。它接受两个参数:起始索引和长度(可选)
string str1 = "abcdefghijkl";string str2 = str1.substr(1, 10);cout << str2 << endl;
- 插入删除和替换操作:
string str1 = "hello";
str1.insert(5, " world");// 表示在第5个字符后插入字符串string str1 = "hello world";
str1.erase(5, 3); // 删除第5个字符之后的3个字符string str1 = "hello world";
str1.replace(5, 6, "C++"); // 从第5个字符后开始替换,替换6个字符,替换为“C++”
- 查找字符串:
find()函数可以查找子字符串或字符的第一个出现位置,如果没有找到,find()会返回std::string::npos,这里因为我开头用了using namespace std;,所以不需要再用std::声明
string str1 = "hello world";if (str1.find("world") != string::npos){cout << "I find it" << endl;}else{cout << "I can't find it" << endl;}
- C++风格字符串与C风格字符串转换:
// `std::string` 转换为C风格字符串(`const char*`)string str1 = "hello world";const char *str2 = str1.c_str();cout << str2 << endl;// C风格字符串转换为 `std::string`const char *str1 = "hello world";string str2(str1);cout << str2 << endl;
- 内存管理:string会自动处理内存分配和释放,不需要手动管理内存。string通过深拷贝的方式处理赋值操作,确保每个字符串对象都有自己独立的内存。
- 什么是深拷贝?什么是浅拷贝?
- 深拷贝:深拷贝是在拷贝的时候将内容申请内存,重新拷贝一份,放到内存中,指针指向这个新拷贝的部分,这样就不会出现析构的时候重复释放的问题了。
- 浅拷贝:浅拷贝就是增加了一个指向相同堆区的指针,这将导致在析构的时候会重复释放。默认的拷贝构造和运算符重载都是浅拷贝。
- 什么是析构:析构(Destructor)是一个特殊的成员函数,用于在对象生命周期结束时清理资源并执行必要的清理工作。析构函数的主要目的包括释放对象在其生命周期内分配的动态内存、关闭文件句柄、释放网络连接等。简单理解就是清理资源的成员函数。
函数
- 函数可以设置默认参数,如果调用时不传入参数则使用默认参数值:
void nameCountry(string name = "China")
{cout << name << endl;
}
- 指针传递和引用传递:
- 指针传递在C语言和C++中都能使用,指针传递是通过传递变量的地址来间接修改变量的值。
- 引用传递,只能在C++中使用。如下第一种函数就是引用传递。即直接操作传入的变量的引用,传递给函数时,函数内部对引用变量的修改会直接反映到原始变量上。
void swap(int &a, int &b)
{int temp = a;a = b;b = temp;
}void swap(int *a, int *b)
{int temp = *a;*a = *b;*b = temp;
}
- 函数的重载:是一种允许在同一个作用域内定义多个具有相同名字但参数列表不同的函数的特性。
- 重载规则:
- 参数的类型不同
- 参数的个数不同
- 参数的顺序不同
- 不允许重载的情况:
- 仅有返回值不同(函数的返回类型不能作为函数重载的依据)
- 函数使用默认参数时,可能会导致重载冲突(默认参数的存在导致二义性)
const修饰符可以参与函数重载。- 数组和指针的重载:数组类型会退化为指针。(在 C语言 中,数组作为函数参数时也会 退化为指针。)
- 重载规则:
// 原始参照
int funcPlus(int x, double y)
{ cout << "这是funcPlus1" << endl; return x + (int)y;
} // 参数类型不同
int funcPlus(double x, double y)
{ cout << "这是funcPlus2" << endl; return (int)(x + y);
} // 参数个数不同
int funcPlus(int x)
{ cout << "这是funcPlus3" << endl; return x * x;
} // 参数顺序不同
int funcPlus(double x, int y)
{ cout << "这是funcPlus4" << endl; return (int)(x + y);
}// 以下这种重载也是不允许的
int func(int x, int y = 10)
{ cout << "这是funcPlus5" << endl; return x + (int)y;
} int func(int x)
{ cout << "这是funcPlus6" << endl; return x;
}void func(int &x); // 非 const 引用
void func(const int &x); // const 引用,允许重载// 下面这两种不允许重载,因为数组arr[]会退化为指针
void func(int arr[])
{ cout << "arr[]" << endl; cout << arr[0] << endl;
} void func(int *arr)
{ cout << "*arr" << endl; cout << arr[0] << endl;
}
类与多态性
- OOP:面向对象编程
- 类在声明时是不申请内存的,只有在实例化时才会初始化(分配)内存
- C++支持类的多继承;Java不支持类的多继承(但支持接口的多继承)
class Person
{
private:int age;public:string name;Person(int a, string name);~Person(); // 析构函数
};// 类内声明,类外定义
Person::Person(int age, string name)
{cout << "构造函数执行:" << endl;this->age = age;this->name = name;
}Person::~Person()
{cout << "析构函数执行:" << endl;
}
- 析构函数的作用:主要作用是在对象的生命周期结束时执行清理工作。
- 释放动态分配的内存:运行过程中通过
new或malloc等函数动态分配了内存,析构函数负责调用delete或free来释放这些内存。 - 释放其他系统资源:对象可能持有除内存以外的系统资源,比如文件句柄、网络连接、数据库连接等。
- 执行其他清理工作:析构函数可以用于任何需要在对象销毁时执行的操作,比如保存数据、记录日志等。
- 析构函数不接受参数,不能重载。
- 如果创建了多个实例,析构函数就会执行多次。
- 释放动态分配的内存:运行过程中通过
- 类的访问控制:
public:公开的成员可以在类外部访问。private:私有的成员只能在类内部访问,不能直接在类外部使用,但可以通过类方法间接调用。protected:受保护的成员可以在类内部和派生类(如子类)中访问。
- 类的静态成员:
- 静态成员变量:属于类本身,而不是某个对象。它在所有对象中共享。
- 静态成员函数:只能访问静态成员变量,不依赖于对象。静态成员可以通过类名直接调用,如:
Person::getCount()其中Person是类名,getCount()是静态成员函数
- 继承:
- 继承 允许一个类(派生类)从另一个类(基类)继承属性和行为。
- C++支持单继承和多继承。
- 派生类可以直接使用基类的公有和受保护成员。
class Animals
{
public:void eat(){cout << "eating" << endl;}
};class Dog : public Animals
{
public:void bark(){cout << "wow wow" << endl;}
};
- 友元函数:友元函数不是类的成员函数,但可以访问类的私有和受保护成员。它是在类外定义的,但具有特殊权限。
class Person
{
private:int age;public:Person(int age){this->age = age;}friend void getAge(Person);
};void getAge(Person per)
{cout << "岁数是:" <<per.age << endl;
}
- 多态:
- 多态性允许同一个函数或方法在不同的对象上表现出不同的行为。
- C++ 中的多态性通过虚函数、继承和指针或引用实现。
- 基本概念:
- 编译时多态(静态多态):通过函数重载和运算符重载实现,编译时决定。
- 运行时多态(动态多态):通过继承和虚函数实现,运行时决定。
- 虚函数:
sound()是基类Animal中的虚函数,Dog和Cat类分别重写了这个函数。- 在运行时,
animalPtr指向不同的派生类对象时,会根据实际对象的类型来调用相应的sound()方法,这就是 运行时多态。
- 纯虚函数与抽象类:
- 纯虚函数 是在基类中声明但没有实现的虚函数。
- 通过定义纯虚函数,基类变为 抽象类,它不能被实例化,只能作为派生类的基类使用。
- 纯虚函数与抽象类的代码如下:
#include <iostream>
using namespace std;class Animal
{
public:virtual void sound() = 0;
};class Dog : public Animal
{
public:// override 关键字不是必须的,但它是一个强烈推荐使用的修饰符。void sound() override{cout << "Dog barks" << endl;}
};class Cat : public Animal
{
public:void sound() override{cout << "Cat meow" << endl;}
};int main(int argc, char const *argv[])
{Animal *animalptr;Dog dog;Cat cat;// 基类指针指向派生类对象animalptr = &dog;animalptr->sound(); // 输出Dog barksanimalptr = &cat;animalptr->sound(); // 输出Cat meowreturn 0;
}
- 多态与析构函数:
- 通过基类指针删除派生类对象时,如果基类的析构函数不是
virtual,则可能会发生 内存泄漏。 - 因为如果基类指针的析构函数不是虚函数,那么通过基类指针删除派生类对象时,调用的是基类的析构函数,导致派生类的资源没有被正确释放
- 通过基类指针删除派生类对象时,如果基类的析构函数不是
- 代码如下:
#include <iostream>
using namespace std;class Base
{
public:virtual ~Base(){ // 虚析构函数cout << "基类 析构函数执行" << endl;}
};class Derived : public Base
{
public:~Derived() override{cout << "派生类 析构函数执行" << endl;}
};int main()
{Base *basePtr = new Derived;delete basePtr; // 先调用派生类的析构函数,再调用基类的析构函数return 0;
}
- 对象切片:
- 如果通过 值传递(而非指针或引用)传递对象,会发生 对象切片,即派生类对象的派生部分会被切掉,变成一个基类对象。
#include <iostream>
using namespace std;class Base
{
public:virtual void show(){cout << "Base show" << endl;}
};class Derived : public Base
{
public:void show() override{cout << "Derived show" << endl;}
};void display(Base &obj) // 通过引用传递对象不会导致“对象切片”
// void display(Base obj) // 值传递会导致“对象切片”
{obj.show();
}int main()
{Derived d;display(d);return 0;
}
- 对象传递最好是传递指针或者引用,直接进行值传递会导致对象切片:
#include <iostream>using namespace std;class Animal
{
public:virtual void sound(){cout << "Animal sound" << endl;}
};class Dog : public Animal
{
public:void sound() override{cout << "Dog barks" << endl;}
};int main(int argc, char const *argv[])
{Dog dog;dog.sound(); // 输出是Dog barksAnimal *basePtr = &dog;basePtr->sound(); // 输出是Dog barksAnimal &baseRef = dog;baseRef.sound(); // 输出是Dog barksAnimal baseObj = dog;baseObj.sound(); // 输出是Animal sound(这里产生了对象切片)return 0;
}
相关文章:
C++入门(有C语言基础)
string类 string类初始化的方式大概有以下几种: string str1;string str2 "hello str2";string str3("hello str3");string str4(5, B);string str5[3] {"Xiaomi", "BYD", "XPeng"};string str6 str5[2];str…...
第四届高性能计算与通信工程国际学术会议(HPCCE 2024)
目录 大会简介 主办单位,承办单位 征稿主题 会议议程 参会方式 大会官网:www.hpcce.net 大会简介 第四届高性能计算与通信工程国际学术会议(HPCCE 2024)将于2024年11月22-24日在苏州召开。HPCCE 2024将围绕“高性能计算与通信工…...
负载均衡架构解说
负载均衡架构是一种设计模式,用于在多个服务器之间分配网络或应用流量,以提高资源利用率、最大化吞吐量、减少响应时间,并确保高可用性。 负载均衡架构的关键组件和概念: 关键组件 1.负载均衡器(Load Balancer&…...
【异常数据检测】孤立森林算法异常数据检测算法(数据可视化 Matlab语言)
摘要 本文研究了基于孤立森林算法的异常数据检测方法,并在MATLAB中实现了该算法的可视化。孤立森林是一种无监督的异常检测算法,主要通过构建决策树来区分正常数据和异常数据。本文使用真实数据集,通过二维可视化展示了检测结果。实验结果表…...
MKV转MP4丨FFmpeg的简单命令使用——视频格式转换
MKV是一种视频封装格式,很好用,也是OBS的默认推荐录制格式,因为不会突然断电关机而导致整个视频录制文件丢失。 但是MKV无法直接导入PR中剪辑,最直接的方法是将MKV转换为MP4格式,最方便且安全无损的转换方法便是用FFmp…...
git使用“保姆级”教程4——版本回退及分支讲解
一、版本回退 1、历史回退(版本回退)——命令行git reset --hard 版本编号 注意:当前命令会让工作区的内容发生改变,可以理解成历史区(master分支)直接回到工作区比如:从版本4回到版本3,则工作区只会显示版本3的代码内容 1.1、指…...
spring cache,Spring data redis
本项目使用Redis存储缓存数据,如何通过Java去访问Redis? 常用的有Jedis和Lettuce两个访问redis的客户端类库 ,Jedis和Lettuce都是redis提供的。其中Lettuce的性能和并发性要好一些,Spring Boot 默认使用的是 Lettuce 作为 Redis …...
10.数据结构与算法-线性表的应用(线性表与有序表的合并)
线性表的合并 有序表的合并 顺序表 链表...
GAN|对抗| 生成器更新|判别器更新过程
如上图所示,生成对抗网络存在上述内容: 真实数据集;生成器;生成器损失函数;判别器;判别器损失函数;生成器、判别器更新(生成器和判别器就是小偷和警察的关系,他们共用的…...
day01——登录功能
逻辑: 前端将登录信息通过报文的形式,发送给后端。后端进行登陆验证 2.1 根据接受的用户名,查询数据表。 若不存在该用户的记录,返回用户不存在。 若用户存在,判断数据库中的密码和接收的是否一致,不一致则…...
Flutter中使用FFI的方式链接C/C++的so库(harmonyos)
Flutter中使用FFI的方式链接C/C库(harmonyos) FFI plugin创建和so的配置FFI插件对so库的使用 FFI plugin创建和so的配置 首先我们可以根据下面的链接生成FFI plugin插件:开发FFI plugin插件 然后在主项目中pubspec.yaml 添加插件的依赖路径&…...
【C++】二义性
在C中,二义性(ambiguity)通常指的是编译器无法确定使用哪个函数、变量或类成员的情况。这种不确定性通常是由于继承和多态特性导致的。下面是一些常见的产生二义性的场景以及如何解决它们的方法: 1. 多重继承中的二义性 当一个类…...
高并发内存池(五):ThreadCache、CentralCache和PageCache的内存回收机制、阶段性代码展示和释放内存过程的调试
目录 ThreadCache的内存回收机制 补充内容1 补充内容2 补充内容3 补充内容4 ListTooLong函数的实现 CentralCache的内存回收机制 MapObjectToSpan函数的实现 ReleaseListToSpans函数的实现 PageCache的内存回收机制 补充内容1 补充内容2 ReleaseSpanToPageCache函…...
STL之stackqueue篇(上)探索C++ STL中的Queue与Stack——构建数据处理的基础框架
文章目录 前言一、stack1.1 定义与基本概念1.2 底层容器1.3 成员函数1.4 使用示例1.5 注意事项1.6 应用场景 二、queue2.1 定义与基本概念2.2 底层容器2.3 成员函数2.4 使用示例2.5 注意事项2.6 应用场景 前言 本文旨在深入探讨C STL中的queue与stack容器,从它们的…...
代码随想录算法训练营Day13
110.平衡二叉树 力扣题目链接:. - 力扣(LeetCode) 后序迭代 class Solution {public boolean isBalanced(TreeNode root) {return getHeight(root)!-1;}public int getHeight(TreeNode root){if(rootnull){return 0;}int leftheightgetHei…...
基于STM32的智能门禁系统
目录 引言项目背景环境准备 硬件准备软件安装与配置系统设计 系统架构关键技术代码示例 RFID数据采集与处理门禁控制实现显示与报警功能应用场景结论 1. 引言 智能门禁系统在现代安防中占据重要地位,通常用于控制进入和离开特定区域的权限。通过基于STM32微控制器…...
[EBPF] 实时捕获DM数据库是否存在SQL阻塞
1. 介绍 eBPF(extened Berkeley Packet Filter)是一种内核技术,它允许开发人员在不修改内核代码的情况下运行特定的功能。eBPF 的概念源自于 Berkeley Packet Filter(BPF),后者是由贝尔实验室开发的一种网…...
秋招内推--招联金融2025
【投递方式】 直接扫下方二维码,或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus,使用内推码 igcefb 投递) 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…...
Unity2022.3.x各个版本bug集合及推荐稳定版本
最近升级到Unity2022,发现以下问题,仅作参考 2022.3.0f1 - 2022.3.6f1 粒子渲染到RenderTexture闪屏 https://issuetracker.unity3d.com/issues/android-vulkan-visualisation-corruption-occurs-when-rendering-particles-to-render-texture 2022.3.…...
SparkSQL-性能调优
祝福 在这个举国同庆的时刻,我们首先献上对祖国的祝福: 第一,我们感谢您给我们和平的环境,让我们能快乐生活 第二,祝福我们国家未来的路越走越宽广,科技更发达,人民更幸福 第三,…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
