力扣 无重复字符的最长字串-3

无重复字符的最长字串-3

class Solution {
public:// 解决方法:双指针int lengthOfLongestSubstring(string s) { // 如果字符串为空,直接返回0if (s.length() == 0)return 0;// 如果字符串不为空,字符串每个字符都不同的情况下,最长字串的长度为1,所以Max初始化为1int left = 0, right = 0, Max = 1;//字符变量t用来存放每次两个指针范围内的后一个字符,用于与两个指针范围内的所有元素判断是否相同char t = 0;while (left < s.length()) {while (right < s.length() - 1) {//flag初始化为1用于标记,方便后续判断int flag = 1;//t赋值为两个指针范围内的后一个字符t = s[right + 1];//循环判断t是否与两个指针内有相同的字符for (int f = left; f <= right; f++) {//如果有相同字符flag标记为0,并break结束循环if (s[f] == t) {flag = 0;break;}}/*如果flag为零,说明双指针范围的后一个字符与双指针范围内有相同字符,后续的字符也没有必要判断了,break结束循环因为此情况下无论范围再怎么扩大(right++),双指针范围内总是有这个的重复字符,不符合题意。*/if (flag == 0)break;/*如果flag为1,说明双指针范围的后一个字符与双指针范围内没有相同字符,则把双指针范围的后一个字符括入到双指针范围内(right++)并与Max比较找到最大字串*/if (flag) {right++;Max = max(Max, right - left + 1);}}//内层while循环结束说明,字符串从头到尾已经遍历完,或者找到了相同字符break结束循环了//那么继续缩小左指针的范围(left),继续从左值针的位置开始查找最长字串,一直找到结尾left++;right = left;}return Max;}
};

每日问题

什么是 C++ 中的移动语义?它的作用是什么?

C++中的移动语义

        移动语义是C++11中引入的一种特性,通过引入右值引用(T&&),支持资源的高效转移,而无需昂贵的拷贝操作。移动语义的核心作用是通过移动而不是复制的方式管理资源,从而提升程序性能,特别是在处理动态分配的资源(如内存、文件句柄等)时。、

移动语义的关键概念

1.右值引用(T&&):

        是一个能够绑定到右值(临时对象)的引用类型。

        它允许开发者直接访问右值对象的资源,并安全地将资源转移到其他对象中。

2.移动构造函数和移动赋值运算符:

        是实现移动语义的两大工具。

        它们负责接收一个右值引用参数,从而将资源从一个对象移动到另一个对象。

作用

1.提高性能:

        在传递或返回大型对象时,通过移动语义可以避免昂贵的拷贝操作,直接转移资源的所有权。

        常用于容器类(如std:vector)在插入、删除或交换元素时。

2.避免资源浪费:

        临时对象通常会在作用域结束时被销毁,移动语义使得这些资源可以被重复利用,而不是浪费掉。

3.支持现代化C++编程:

        与标准库(如std:move)结合,为开发者提供了更多灵活性和效率。

移动语义的实现

移动构造函数
class MyClass {
private:int* data;public:// 构造函数MyClass(int value) : data(new int(value)) {}// 移动构造函数MyClass(MyClass&& other) noexcept : data(other.data) {other.data = nullptr; // 资源转移,确保原对象不再持有资源}// 析构函数~MyClass() {delete data; // 释放资源}
};
  • 这是一个移动构造函数,接受一个右值引用 other(右值或临时对象)。
  • 实现了资源转移:
    • 将 other.data 的值转移给当前对象的 data。
    • 将 other.data 置为 nullptr,避免原对象在销毁时重复释放资源。
  • noexcept 表示此操作不会抛出异常,确保移动操作在某些场景(如标准容器的优化)中安全进行。
移动赋值运算符
class MyClass {
private:int* data;public:// 构造函数MyClass(int value) : data(new int(value)) {}// 移动赋值运算符MyClass& operator=(MyClass&& other) noexcept {if (this != &other) {         // 防止自我赋值delete data;              // 释放当前资源data = other.data;        // 转移资源other.data = nullptr;     // 确保原对象不再持有资源}return *this;}~MyClass() {delete data;}
};
配合标准库使用
1.std::move

        用于将一个左值显示转换为右值,从而启用移动语义。

        常见用法时将一个临时对象的资源转移到另一个对象中。

示例:

std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = std::move(v1); // v1 的资源转移到 v2,避免拷贝
2.std::forward

        通常用于完美转发函数模板参数,确保参数的值类别(左值或右值)正确传递。

使用场景

1.容器优化:

        C++标准库容器(如std::vector、std::string)在插入或删除元素时,利用移动语义大幅减少不必要的拷贝。

2.返回值优化:

        函数返回临时对象时,可以直接移动对象资源,避免临时对象的构造和销毁。

示例:

MyClass createObject() {MyClass obj(42);return obj; // 编译器自动应用移动语义
}

3.避免多余的动态分配:

        动态资源管理类(如文件句柄、数据库连接)可以通过移动语义避免资源的重复分配和释放。

移动语义是 C++11 的重要特性,专注于高效的资源管理和性能优化。它通过右值引用、移动构造函数和移动赋值运算符,避免了不必要的拷贝操作,特别适合处理动态资源密集型任务。在现代 C++ 编程中,移动语义和标准库(如 std::move)的结合已经成为编写高效代码的重要工具。

右值引用是什么?如何使用右值引用实现移动语义?

右值引用是什么?

        右值引用(T&&)是C++11引入的一种新类型引用,允许程序员直接操作右值(临时对象)。右值引用的主要目的是支持移动语义和完美转发。

右值与左值的区别

左值:表示一个内存中有确定存储地址的对象,可以被持久引用或操作。

        例如:变量名、数组元素。

        int a = 5;中的a是左值。

右值:表示临时对象或者表达式结果,通常无法直接获取地址。

        例如:字面值、临时对象、函数返回的非引用置。

        5、a + b的结果是右值。

        右值引用可以绑定到右值上,与普通左值引用(T&)不同。

右值引用的语法

int&& r = 10;  // r 是右值引用,绑定到字面值 10
int x = 20;
int&& r2 = x + 5;  // r2 是右值引用,绑定到临时值 25

右值引用允许我们直接获取右值的资源,并通过移动语义避免拷贝操作。

右值引用和移动语义

        移动语义的核定是将资源从一个对象“移动”到另一个对象,而不是“拷贝”它们。右值引用在实现移动语义时扮演了关键角色。

传统拷贝vs移动

1.传统拷贝:

        创建一个对象的完整副本,可能会涉及动态资源的重新分配。

        成本较高,特别是对动态内存的管理类(如vector)。

        例如:

std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = v1; // 复制 v1 的内容,可能导致多次内存分配
2.移动:

        通过右值引用,将一个对象的资源直接转移到另一个对象。

        避免了不必要的内存分配和数据复制,提高性能。

        示例:

std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = std::move(v1); // v1 的资源转移到 v2,v1 被置为“空”

如何使用右值引用实现移动语义

        为了实现移动语义,需要提供移动构造函数和移动赋值运算符。

1.移动构造函数

        移动构造函数接受一个右值引用作为参数,将资源从右值对象转移到当前对象。

        示例:

class MyClass {
private:int* data;public:// 构造函数MyClass(int value) : data(new int(value)) {}// 移动构造函数MyClass(MyClass&& other) noexcept : data(other.data) {other.data = nullptr; // 将原对象的资源置为空}// 析构函数~MyClass() {delete data; // 释放资源}
};
2.移动赋值运算符

        移动赋值运算符转移资源时需要释放当前对象已有的资源(避免内存泄漏),然后接管右值对象的资源。

        示例:

class MyClass {
private:int* data;public:// 构造函数MyClass(int value) : data(new int(value)) {}// 移动赋值运算符MyClass& operator=(MyClass&& other) noexcept {if (this != &other) {      // 避免自我赋值delete data;           // 释放当前对象的资源data = other.data;     // 转移资源other.data = nullptr;  // 将原对象的资源置为空}return *this;}// 析构函数~MyClass() {delete data;}
};

完整示例:

#include <iostream>
#include <utility> // for std::moveclass MyClass {
private:int* data;public:// 构造函数MyClass(int value) : data(new int(value)) {std::cout << "Constructing: " << *data << std::endl;}// 移动构造函数MyClass(MyClass&& other) noexcept : data(other.data) {other.data = nullptr;std::cout << "Moving: " << *data << std::endl;}// 移动赋值运算符MyClass& operator=(MyClass&& other) noexcept {if (this != &other) {delete data;data = other.data;other.data = nullptr;std::cout << "Assigning: " << *data << std::endl;}return *this;}// 析构函数~MyClass() {if (data) {std::cout << "Destructing: " << *data << std::endl;delete data;} else {std::cout << "Destructing: nullptr" << std::endl;}}
};int main() {MyClass obj1(10);              // 调用构造函数MyClass obj2 = std::move(obj1); // 调用移动构造函数MyClass obj3(20);obj3 = std::move(obj2);        // 调用移动赋值运算符return 0;
}

输出:

Constructing: 10
Moving: 10
Constructing: 20
Assigning: 10
Destructing: nullptr
Destructing: nullptr
Destructing: 10

右值引用允许我们绑定到右值(临时对象),直接操作其资源。

移动语义通过右值引用实现,主要通过 移动构造函数 和 移动赋值运算符,实现高效的资源转移。

使用右值引用和 std::move 可以显著提升程序性能,特别是当类中包含动态资源(如内存、文件句柄)时。

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

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

相关文章

如何在Ubuntu当中利用CloudCompare软件进行点云配准拼接?

1.首先需要安装相应的cloudcompare软件&#xff0c;以下有两种方式&#xff1a;第一种直接在ubuntu的软件商店里搜索CloudCompare软件进行install&#xff0c;我这里已经安装完毕。 方式二&#xff1a;可以直接原码安装&#xff1a; github地址&#xff1a; https://github.co…

贴贴,一款windows剪切板管理软件

贴贴&#xff0c;一款windows剪切板管理软件 软件下载官网 https://tietieapp.com 软件界面 软件界面简洁、信息展示清晰。软件会自动记录你复制过的内容。包括哪个软件复制的、复制的时间。支持图片、文本、文件等多种格式。支持持久化&#xff0c;电脑重启记录仍然存在。支持…

泷羽sec学习打卡-html基础

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 关于云技术基础的那些事儿-捕获帅照 html基础什么是html&#xff1f; 常用的html标签html示例 css基础什…

RocketMQ的使⽤

初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种⽅式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要⻢上回复。 两种⽅式各有优劣&#xff0c;打电话可以⽴即得到响应&#xff0c;但…

java 字符 ASCII码 详解

在 Java 中&#xff0c;字符 (char) 和 ASCII 码的关系是通过 Unicode 字符集建立的。以下是 Java 中字符与 ASCII 码相关的详解。 1. 什么是 ASCII 和 Unicode&#xff1f; ASCII (American Standard Code for Information Interchange) ASCII 码 是一种字符编码标准&#x…

初试无监督学习 - K均值聚类算法

文章目录 1. K均值聚类算法概述2. k均值聚类算法演示2.1 准备工作2.2 生成聚类用的样本数据集2.3 初始化KMeans模型对象&#xff0c;并指定类别数量2.4 用样本数据训练模型2.5 用训练好的模型生成预测结果2.6 输出预测结果2.7 可视化预测结果 3. 实战小结 1. K均值聚类算法概述…

JSON,事件绑定

文章目录 JSON事件绑定输入框input和div的内容返回获取dom元素数组还是单个对象for循环为什么要写const那一行&#xff0c;直接写 hobbys[index].checked true;可以吗const不是常量吗&#xff0c;为什么用const声明的element的属性值可以改变&#xff1f; 黑马学习笔记 JSON 定…

学习HTML第三十一天

学习文章目录 七. 普通按钮八. 文本域九.下拉框 七. 普通按钮 注意点&#xff1a;普通按钮的 type 值为 button &#xff0c;若不写 type 值是 submit 会引起表单的提交 八. 文本域 常用属性如下&#xff1a; rows 属性&#xff1a;指定默认显示的行数&#xff0c;会影响文…

基于Multisim的汽车尾灯控制电路设计与仿真

1、电路由四个按键控制&#xff0c;分别对应左转、右转、刹车和检查。 2、当左转或右转键按下时,左侧或右侧的 3个汽车尾灯按照左循环或右循环的顺!2/3 点亮&#xff0c;点亮时间为 1秒。 3、当刹车时&#xff0c;所有的尾灯同时闪烁&#xff0c;闪烁时间为1秒。 4、当检查时…

7天掌握SQL - 第三天:MySQL实践与索引优化

目录 安装MySQL创建数据库和表结构SQL语句实操练习MySQL高级特性索引设计与优化总结 1. 安装MySQL 1.1 下载与安装 MySQL可以通过官方网站下载安装包。以下是安装MySQL的基本步骤&#xff1a; 访问MySQL官方网站 MySQL Downloads。选择适合您操作系统的版本进行下载。安装…

osg、osgearth简介及学习环境准备

一、osg简介&#xff08;三维场景图渲染与调度引擎&#xff09; OSG是Open Scene Graphic 的缩写&#xff0c;OSG于1997年诞生于以为滑翔机爱好者之手&#xff0c;Don burns 为了对滑翔机的飞行进行模拟&#xff0c;对openGL的库进行了封装&#xff0c;osg的雏形就这样诞生了&…

小程序-使用 iconfont 图标库报错:Failed to load font

官方默认可以忽略此错误&#xff0c;在清除缓存后首次刷新会显示此错误&#xff0c;重新渲染错误消失 解决方法&#xff1a; 在 iconfont 图标库选择项目设置 选中 Base64 保存&#xff0c;重新点击链接 -> 复制代码到项目中 操作步骤&#xff1a;

GEE 训练教程——Sentinel-1的卷积(核函数)的分析和可视化

目录 简介 函数 convolve(kernel) Arguments: Returns: Image ee.Kernel.fixed(width, height, weights, x, y, normalize) Arguments: Returns: Kernel 代码解释 代码 结果 简介 GEE 训练教程——Sentinel-1的卷积(核函数)的分析和可视化 函数 convolve(kerne…

Stable Diffusion的解读(二)

Stable Diffusion的解读&#xff08;二&#xff09; 文章目录 Stable Diffusion的解读&#xff08;二&#xff09;摘要Abstract一、机器学习部分1. 算法梳理1.1 LDM采样算法1.2 U-Net结构组成 2. Stable Diffusion 官方 GitHub 仓库2.1 安装2.2 主函数2.3 DDIM采样器2.4 Unet 3…

13. 【.NET 8 实战--孢子记账--从单体到微服务】--简易权限--完善TODO标记的代码

这篇文章特别短&#xff0c;短到可以作为一篇文章的一个章节&#xff0c;那让我们开始吧 一、编写代码 我们在代码中标记了大量的TODO标记&#xff0c;并且注明了这里暂时写死&#xff0c;等权限和授权完成后再改为动态获取这句话。那么到目前为止和权限有关的代码已经完成了…

Rust “xxx“.to_string()和Rust String::from(“xxx“)区别(将字符串字面量(str类型)转换为String类型)

文章目录 Rust "xxx".to_string()和Rust String::from("xxx")区别1. .to_string()&#xff08;能够将任何可以显示的类型&#xff08;如数字、结构体等&#xff09;转为字符串&#xff09;2. String::from()区别总结&#xff1a;性能&#xff1a;示例对比&…

如何设置谷歌浏览器的家庭保护功能

谷歌浏览器是全球使用最广泛的网络浏览器之一&#xff0c;提供了许多强大的功能和扩展。对于有小孩的家庭来说&#xff0c;设置家庭保护功能可以帮助家长管理孩子的上网行为&#xff0c;确保他们在一个安全、健康的网络环境中浏览网页。本文将详细介绍如何设置谷歌浏览器的家庭…

Vue:后端返回二进制文件,前端如何实现浏览器自动下载?

Vue项目开发中&#xff0c;遇到界面下载功能时&#xff0c;前端如何实现将后端返回二进制文件在浏览器自动下载&#xff1f; 一、关键代码&#xff1a; export function downloadFile(fileName) {axios({method: post,url: process.env.VUE_APP_BASE_API /cgi-bin/file,data:…

dpdk ppe模块细分

在基于 openEuler 系统运行 DPDK&#xff08;Data Plane Development Kit&#xff09; 时&#xff0c;涉及到的 PPE&#xff08;Packet Processing Engine&#xff09; 中的 SSU&#xff08;Service Scheduling Unit&#xff09;、PPP&#xff08;Packet Processing Pipeline&a…

触发器清零引脚要上拉高电平

在使用触发器设计电路时&#xff0c;清零引脚该如何处理呢&#xff1f; 下图中NCLR是清零引脚&#xff0c;由于未使用就悬空了&#xff0c;没有任何电气连接&#xff0c;这样做是不对的。应该上拉至高电平。 加入电阻R3&#xff0c;上拉至3.3V&#xff0c;这样不使用清零功能的…