力扣 无重复字符的最长字串-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;电脑重启记录仍然存在。支持…

RocketMQ的使⽤

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

初试无监督学习 - 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、当检查时…

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

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

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…

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:…

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

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

Vue_Router权限控制:不同角色显示不同路由

写在前面 在Vue中&#xff0c;Router是一个官方提供的用于处理应用程序路由的插件。它允许我们创建单页应用程序&#xff08;SPA&#xff09;&#xff0c;其中不同的页面和组件可以通过URL进行导航和展示。使我们可以轻松地创SPA&#xff0c;并实现可复用和可组合的组件…

设计模式之 适配器模式

适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户端所期望的另一个接口。通过使用适配器模式&#xff0c;原本由于接口不兼容的类可以进行协作。简单来说&#xff0c;适配器模式就是将不兼容的接口连接起来&…

【LLM训练系列02】如何找到一个大模型Lora的target_modules

方法1&#xff1a;观察attention中的线性层 import numpy as np import pandas as pd from peft import PeftModel import torch import torch.nn.functional as F from torch import Tensor from transformers import AutoTokenizer, AutoModel, BitsAndBytesConfig from typ…

萨瑞MCU R7FA8D1BH环境搭建教程

萨瑞MCU R7FA8D1BH环境搭建教程 如果你是大学生 遇到电子技术 学习 成长 入行难题 佳喔威信&#xff0c;给你提供一定资源和战略方法上的帮助 相信我的专业职业经历一定能帮到你 目录 概述 2. 开发板介绍3. 搭建rtthread环境4. 安装瑞萨的keil环境5. 搭建瑞萨的keil辅助环境…

鸿蒙实战:使用显式Want启动Ability

文章目录 1. 实战概述2. 实现步骤2.1 创建鸿蒙应用项目2.2 修改Index.ets代码2.3 创建SecondAbility2.4 创建Second.ets 3. 测试效果4. 实战总结5. 拓展练习 - 启动文件管理器5.1 创建鸿蒙应用项目5.2 修改Index.ets代码5.3 测试应用运行效果 1. 实战概述 本实战详细阐述了在 …

PH热榜 | 2024-11-19

DevNow 是一个精简的开源技术博客项目模版&#xff0c;支持 Vercel 一键部署&#xff0c;支持评论、搜索等功能&#xff0c;欢迎大家体验。 在线预览 1. Layer 标语&#xff1a;受大脑启发的规划器 介绍&#xff1a;体验一下这款新一代的任务和项目管理系统吧&#xff01;它…

React Native 基础

React 的核心概念 定义函数式组件 import组件 要定义一个Cat组件,第一步要使用 import 语句来引入React以及React Native的 Text 组件: import React from react; import { Text } from react-native; 定义函数作为组件 const CatApp = () => {}; 渲染Text组件