C++mutable

news2024/9/21 1:48:40

文章目录

  • Claude 讲解
    • 基本用法
    • mutable的常见用途
    • 注意事项
  • ChatGpt 讲解
      • 1. 基本概念
      • 2. 使用示例
        • 解释:
      • 3. 适用场景
      • 4. 注意事项
    • lambda 讲解
      • 基本语法
      • 示例
      • 捕获方式
      • 使用场景
    • mutable 和 labmda 一起使用
      • 代码:
      • 代码分析:
      • 输出结果:

在C++编程中, const关键字通常用于保证对象的不可变性,从而提高代码的安全性和可维护性。然而,有时我们会遇到这样的需求:希望在某些特定的成员变量上保留修改的灵活性,即使它们属于一个 const对象。为了解决这个矛盾,C++提供了 mutable关键字,它允许我们在严格遵守 const约束的同时,依然能够修改某些特定的成员变量。本文将带你深入探讨 mutable的使用场景及其应用。

Claude 讲解

mutable是C++中的一个关键字,用于修饰类的成员变量。它的主要作用是允许在const成员函数中修改被mutable修饰的成员变量。这打破了const成员函数不能修改对象状态的一般规则。

让我们通过几个例子来理解mutable的用法:

基本用法

class Counter {
private:
    mutable int count = 0;

public:
    void increment() const {
        ++count;  // 可以在const函数中修改mutable成员
    }

    int getCount() const {
        return count;
    }
};

int main() {
    const Counter c;
    c.increment();  // 合法,尽管c是const对象
    std::cout << c.getCount();  // 输出1
    return 0;
}

在这个例子中,尽管increment()是一个const成员函数,但它仍然可以修改count成员,因为count被声明为mutable。

mutable的常见用途

mutable通常用于以下场景:

a) 缓存: 当某个计算很昂贵,我们想在const对象中缓存结果时。

b) 互斥锁: 在多线程环境中,即使对象是const的,我们也可能需要锁定资源。

c) 计数器或统计信息: 如上面的例子所示。

注意事项

  • 过度使用mutable可能会导致代码难以理解和维护。
  • mutable不应该用来绕过const的语义,而应该用于那些不影响对象逻辑状态的情况。

ChatGpt 讲解

在C++中,mutable关键字用于允许类的某些成员变量在常量对象中被修改。通常情况下,当你声明一个对象为常量(即使用const关键字),这个对象的所有成员都不允许被修改。但在某些情况下,你可能希望某些成员能够在常量对象中被修改,此时就可以使用mutable关键字。

1. 基本概念

当一个类的成员被声明为mutable时,即使对象是const的,也允许该成员被修改。mutable关键字通常用于标识那些不影响对象逻辑状态的成员变量,例如用于缓存、计数器等。

2. 使用示例

以下是一个简单的示例,展示了mutable关键字的用法:

#include <iostream>

class Counter {
private:
    mutable int counter = 0; // 使用 mutable 关键字
public:
    void increment() const {
        counter++; // 即使在 const 方法中,mutable 变量也可以被修改
    }

    int getCounter() const {
        return counter;
    }
};

int main() {
    const Counter c;
    c.increment();
    std::cout << "Counter: " << c.getCounter() << std::endl; // 输出: Counter: 1
    return 0;
}
解释:
  • 在上面的代码中,Counter类中包含一个私有成员变量counter,它被声明为mutable
  • increment方法被声明为const,这意味着它不能修改对象的状态。然而,由于counter被声明为mutable,它仍然可以在increment方法中被修改。
  • 最终,main函数中的c.increment()可以成功地增加counter的值,即使c本身是一个常量对象。

3. 适用场景

  • 缓存机制:当你想在一个const成员函数中修改一些缓存数据,而这些数据对类的逻辑状态没有影响时,可以使用mutable
  • 日志记录:当你在一个const成员函数中想记录一些日志信息,并且需要修改日志数据时,可以使用mutable

4. 注意事项

  • mutable只能用于非静态成员变量。
  • mutable并不会绕过const的保护机制;它仅允许特定成员变量在const对象中被修改,因此应谨慎使用,确保不会误修改对象的逻辑状态。

mutable关键字在C++中为管理对象的可变性提供了更大的灵活性,尤其是在需要处理类似缓存或日志记录的场景时非常有用。
在这里插入图片描述

在这里插入图片描述

lambda 讲解

在C++中,lambda表达式是一种可以在本地定义匿名函数的方式。它们在C++11标准中被引入,并且在C++14和C++17中得到了进一步的扩展。lambda表达式非常适合用于需要在短时间内定义并使用函数的情况,比如在STL算法中作为回调函数。

基本语法

一个lambda表达式的基本语法如下:

[capture](parameters) -> return_type {
    // function body
};
  • capture:捕获列表,用于指定lambda表达式可以使用哪些外部变量。
  • parameters:参数列表,类似于普通函数的参数列表。
  • return_type:返回类型(可选,如果可以从函数体推断出返回类型,则可以省略)。
  • function body:函数体,包含实际执行的代码。

示例

  1. 简单的lambda表达式:
auto add = [](int a, int b) {
    return a + b;
};

int result = add(3, 4); // result = 7
  1. 带捕获列表的lambda表达式:
int x = 10;
int y = 20;

auto add_with_capture = [x, y](int a) {
    return a + x + y;
};

int result = add_with_capture(5); // result = 35
  1. 捕获所有外部变量:
int x = 10;
int y = 20;

auto add_all = [=](int a) {
    return a + x + y;
};

int result = add_all(5); // result = 35
  1. 捕获外部变量的引用:
int x = 10;

auto increment = [&x]() {
    ++x;
};

increment();
std::cout << x; // 输出 11
  1. 指定返回类型:
auto divide = [](int a, int b) -> double {
    if (b == 0) return 0;
    return static_cast<double>(a) / b;
};

double result = divide(10, 3); // result = 3.33333

捕获方式

捕获列表可以使用多种方式来捕获变量:

  • [x, &y]:按值捕获x,按引用捕获y。
  • [=]:按值捕获所有外部变量。
  • [&]:按引用捕获所有外部变量。
  • [this]:捕获当前对象的this指针(隐式捕获对象的成员)。

使用场景

lambda表达式在很多情况下都非常有用,尤其是在使用STL(标准模板库)的算法时。例如:

std::vector<int> numbers = {1, 2, 3, 4, 5};
std::for_each(numbers.begin(), numbers.end(), [](int &n) { n *= 2; });
// numbers 现在包含 {2, 4, 6, 8, 10}

在这里插入图片描述

mutable 和 labmda 一起使用

代码:

#include <iostream>
#include <string>

class Entity {
public:
    std::string GetName() const {
        return "EntityName";
    }
};

int main() {
    const Entity e; // 常量对象e
    std::cout << e.GetName() << std::endl; // 调用GetName并打印

    int x = 8; // 定义变量x
    auto f = [=]() mutable { // 使用lambda表达式捕获x
        x++; // 因为lambda是mutable的,所以可以修改捕获的x
        std::cout << "x after increment: " << x << std::endl;
    };

    f(); // 调用lambda表达式
    return 0;
}

代码分析:

  1. Entity类的定义

    class Entity {
    public:
        std::string GetName() const {
            return "EntityName";
        }
    };
    
    • 这里定义了一个Entity类,包含一个名为GetName的成员函数,该函数返回一个字符串。
    • GetName函数被声明为const,意味着它不能修改对象的状态。
  2. main函数

    const Entity e;
    std::cout << e.GetName() << std::endl;
    
    • e是一个const Entity对象。
    • std::cout打印了e.GetName()的返回值。
  3. lambda表达式

    int x = 8;
    auto f = [=]() mutable {
        x++;
        std::cout << "x after increment: " << x << std::endl;
    };
    
    • int x = 8; 声明了一个整数变量x并赋值为8
    • auto f = [=]() mutable {...}; 定义了一个lambda表达式:
      • [=]:捕获x的值(通过值捕获)。
      • mutable:允许修改捕获的值(通常通过值捕获的变量在lambda中是只读的,使用mutable后可以修改它)。
      • x++:在lambda内部递增x
      • std::cout << ... 打印修改后的x
  4. 调用lambda

    f();
    
    • 调用lambda表达式f,输出x的值,应该是9

输出结果:

EntityName
x after increment: 9

这个例子展示了const对象如何调用const成员函数,以及mutable关键字在lambda表达式中的作用,使得捕获的值可以被修改。

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

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

相关文章

(详细文档!)JavaSwing图书管理系统+mysql数据库

目 录 1.项目概述及需求分析................................ 1 2.系统设计......................................... 1 2.1程序总体设计......................................... 1 2.2数据库设计........................................... 2 2.3公共模块设计...…

论文学习(一):基于遥感技术的凉山州森林火险预测方法研究

文章目录 摘要部分一、绪论二、研究区历史火情分析2.1凉山州森林火灾年际变化特征2.2凉山州森林火灾月际变化特征2.3凉山州森林火灾空间分布特征2.4森林火灾等级与起火原因分析 三、数据与方法3.1数据来源3.2数据预处理3.3研究方法3.3.1逻辑回归&#xff1a;最大似然估计3.3.2决…

iOS——持久化

iOS的数据存储机制 沙盒机制 应用沙盒文件夹包含了&#xff1a; Application(应用程序包)&#xff1a;包含了所有的资源文件和和可执行文件&#xff0c;上架前经过数字签名&#xff0c;上架后不可修改。 Documents&#xff1a;文档目录&#xff0c;要保存程序生成的数据&…

华为OD机试 - 最大相连男生数 - 矩阵(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

[数据集][目标检测]水面垃圾检测数据集VOC+YOLO格式2027张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2027 标注数量(xml文件个数)&#xff1a;2027 标注数量(txt文件个数)&#xff1a;2027 标注…

信创实践(3):基于x2openEuler将CentOS升级成openEuler,享受其带来的创新和安全特性

引言&#xff1a; 在当前的 IT 行业中&#xff0c;创新和安全性是两大关键趋势。随着 CentOS 停止维护&#xff0c;许多用户正在寻找替代方案&#xff0c;以保持其系统的更新和安全。openEuler 作为一个强大的开源操作系统&#xff0c;成为了理想的迁移目标。本教程将指导您如…

大语言模型的上下文窗口(Context Windows):对人工智能应用的影响

大语言模型&#xff08;LLMs&#xff09;极大地提升了人工智能在理解和生成类人文本方面的能力。其中一个影响其效用的基本方面是它们的 “上下文窗口”—— 这个概念直接影响着这些模型接收和生成语言的有效性。我将深入探讨上下文窗口是什么、它们对人工智能应用的影响以及组…

【通俗理解】Baseline在竞赛中的意义——性能比较的标准尺

【通俗理解】Baseline在竞赛中的意义——性能比较的标准尺 关键词提炼 #Baseline #竞赛标准 #算法性能 #性能比较 #改进评估 #魔改基础 #优势彰显 第一节&#xff1a;Baseline的类比与核心概念【尽可能通俗】 1.1 Baseline的类比 Baseline在竞赛中就像是一场跑步比赛的起跑…

【IEEE独立出版 | 最终截稿时间:2024年9月9日23:59】第三届人工智能、物联网和云计算技术国际会议(AIoTC 2024)

【IEEE独立出版 | 最终截稿时间&#xff1a;2024年9月9日23:59】 第三届人工智能、物联网和云计算技术国际会议&#xff08;AIoTC 2024&#xff09; 2024 3rd International Conference on Artificial Intelligence, Internet of Things and Cloud Computing Technology 202…

轻松驾驭开学季,智慧校园综合解决方案!

智慧校园是指运用先进的信息技术手段和智能化系统&#xff0c;对学校内部各种教育资源、管理流程和服务进行数字化、网络化、智能化的整合与优化&#xff0c;提供高效便捷的教育教学和管理服务环境的校园。 智慧校园建设从哪些方面入手呢&#xff1f; 1.智慧食堂管理系统 基于…

[3.4]【机器人运动学MATLAB实战分析】平面RRR机器人正运动学MATLAB计算

本文重点介绍平面RRR机械手结构的正运动学方程的算例,这些是工业机器人中经常遇到的。平面RRR机器人运动学建模如下: 机器人模型: 表1三连杆平面臂的DH参数 由于所有关节都是转动型的,对每一个关节都具有相同的定义的齐次变换矩阵结构,即: 则计算正运动学方程得:

xAI巨无霸超级计算机上线:10万张H100 GPU,计划翻倍至20万张

在短短四个多月的时间里&#xff0c;埃隆马斯克的X公司&#xff08;前身为Twitter&#xff09;推出了世界上最强劲的人工智能训练系统。名为Colossus的超级计算机使用了多达10万张NVIDIA H100 GPU进行训练&#xff0c;并计划在未来几个月内再增加5万张H100和H200 GPU。 “本周末…

时间序列神器Prophet教程-入门教程

公众号&#xff1a;尤而小屋编辑&#xff1a;Peter作者&#xff1a;Peter 大家好&#xff0c;我是Peter~ 今天给大家分享一个时间序列预测神器Prophet的简易入门教程。 什么是Prophet Prophet是一种基于加法模型的时间序列预测工具&#xff0c;由Facebook的数据科学团队开发…

实战训练与源码教程:用Real-ESRGAN对抗生成超分技术实现超高清图像!

目录 前言 超分数据如何构造呢&#xff1f; Real-ESRGAN 1. 高质量细节重建 2. 真实感和自然度 3. 处理真实世界数据 4. 多尺度和多种类型的输入 5. 视觉效果的提升 超分如何退化 1. 模糊处理 2. 噪声处理 3. 压缩失真 4. 训练数据的退化模拟 2.经典退化模型◆退…

【苍穹外卖】Day 7 缓存、购物车相关接口

1 缓存 存在问题&#xff1a; 用户端小程序展示的菜品数据都是通过査询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 >解决&#xff1a; 通过 Redis 来缓存菜品数据&#xff0c;减少数据库查询操作 缓存逻辑分析&#xff1a; 每个分…

PyDracula:用 PySide6 和 PyQt6打造现代感 Python GUI 的利器

PyDracula 是一个基于 PySide6 或 PyQt6 的 Python GUI 库&#xff0c;它以其现代、美观、易于定制的特点而闻名。PyDracula 融合了流行的 Dracula 主题&#xff0c;并提供了丰富的功能&#xff0c;让开发者可以轻松构建出具有吸引力的图形界面。本文将详细介绍 PyDracula 的核…

【Godot4.3】CanvasShape资源化改造

概述 通过把之前自定义的CanvasShape类变成资源类型&#xff0c;将可以同时用于CanvasItem绘图和创建扩展的Node2D和Polygon2D节点等。 本篇就完成CanvasShape类的资源化改造&#xff0c;并记录改造过程和思路。 CanvasShape资源类型体系 CanvasShape仍然为图形基类&#xf…

Android Auto未来可能支持无线电广播

通过Android Auto&#xff0c;可以在车载收音机上使用 Google 地图、音乐、收听播客&#xff0c;还能获取天气等基本信息。最近&#xff0c;国外科技媒体9to5Google通过分析 Android Auto v12.3 和 v12.4的应用程序的代码发现了一些提示信息&#xff0c;特别提到了 AM、FM、HD …

【Protobuf】xml、json与protobuf有什么区别,protobuf详解(保姆篇)

文章目录 简介Protobuf 的原理安装 Protobuf 编译器在 Python 中使用 Protobuf安装语言特定的 Protobuf 库定义消息结构生成代码使用 Protobuf 进行序列化和反序列化 在 Java 中使用 Protobuf安装和配置编译 .proto 文件使用生成的 Java 类创建和序列化对象 代码注释 高级特性嵌…

LabVIEW灵活集成与调试的方法

在LabVIEW开发中&#xff0c;为了构建一个既便于调试又能灵活集成到主VI中的控制VI&#xff0c;开发者需要采用适当的编程方式和架构。常见的选择包括模块化设计、状态机架构以及事件驱动编程。这些方法有助于简化调试过程、提高系统的稳定性&#xff0c;并确保代码的重用性和可…