条款3:尽量使用const

文章目录

  • const指针和函数声明
    • const修饰指针
    • const修饰函数
    • const修饰容器
    • const应用在函数中
  • const限定成员函数
  • 避免const重载的代码重复
  • 总结

const指针和函数声明

const修饰指针

char greeting[] = "Hello";
char* p = greeting; 	// non-const 指针,// non-const 数据
const char* p = greeting; 	// non-const 指针,// const 数据
char* const p = greeting; // const 指针,// non-const 数据
const char* const p = greeting; // const 指针,// const 数据

 如果const出现在左侧:指向的是常量,const出现在右侧:指针本身是常量。

const修饰函数

void f1(const Widget* pw); // f1接受一个指向常量Widget对象的指针
void f2(Widget const* pw); // f2也一样

 const出现在类型的左边,或右边是等效的。

const修饰容器

std::vector<int> vec;
//...// iter 的行为像 T* const
const std::vector<int>::iterator iter = vec.begin();
*iter = 10; 	// 可以修改指向的数据
++iter; 	// 错误! iter 本身是 const
//cIter 的行为像 const T*
std::vector<int>::const_iterator cIter =vec.begin();
*cIter = 10; 	// 错误! *cIter 是 const
++cIter; 	// 正确, 可以修改迭代器本身

const应用在函数中

 令函数返回一个常量值,往往可以降低因客户错误而造成的意外,下面是一个有理数的例子。

class Rational {  }; // 有理数! 
const Rational operator*(const Rational& lhs, const Rational& rhs);

如果不小心把=写成了==

Rational a, b, c;
(a * b) = c; 	// 对a*b的结果调用operator=
if (a* b = c)  // 糟糕, 写错了,应该是 ==

 但这时候,由于我们返回的是一个const类型的,所以该做法在编译的时候就会提示错误,这也能让我们更快的找到错误。

const限定成员函数

在成员函数上使用const:
1、使类的接口意图更明确。知道哪些函数可以修改一个对象,哪些不能,这很重要。
2、使得使用const对象成为可能。
 C++的一个重要特性:仅在常量上不同的成员函数可以被重载。考虑表示文本块的类:

class TextBlock {
public:TextBlock(std::string str) {text = str;}const char& operator[](std::size_t position) const // const对象的operator[]{return text[position];} char& operator[](std::size_t position) // non-const对象的operator[]{return text[position];} 
private:std::string text;
};void print(const TextBlock& ctb) // 在这个函数中,ctb是const
{std::cout << ctb[0]; // 调用const的TextBlock::operator[]
}//TextBlock的运算符[]可以这样使用:
TextBlock tb("Hello");std::cout << tb[0]; // 调用non-const的TextBlock::operator[]const TextBlock ctb("World");
std::cout << ctb[0]; // 调用const的TextBlock::operator[]print(tb);   // 调用const的TextBlock::operator[]
print(ctb);  // 调用const的TextBlock::operator[]tb[0] = 'x'; //正确
ctb[0] = 'x'; //错误

避免const重载的代码重复

 假设TextBlock中的[]运算符不仅返回对适当字符的引用,还执行边界检查,记录访问信息,甚至可能进行数据完整性验证。

class TextBlock {
public:...const char& operator[](std::size_t position) const{... // do bounds checking... // log access data... // verify data integrityreturn text[position];}char& operator[](std::size_t position) {... // do bounds checking... // log access data... // verify data integrityreturn text[position];}
private:std::string text;
};

这边我们定义了一个const版本和一个非const版本的函数。
替代方案:让operator[]的一个版本调用另一个版本。先写const版本,然后脱离const限制。

class TextBlock {
public:...const char& operator[](std::size_t position) const{// 和前面一样.........return text[position];}char& operator[](std::size_t position){//只需要调用const版本return const_cast<char&>( //对op[]的返回类型抛弃const;//给*this的类型添加const;调用op的const版本[]static_cast<const TextBlock&>(*this)[position] );}...
};

1、在这种情况下,去掉返回值上的const是安全的,因为调用非const操作符[]的人首先必须有一个非const对象。
2、让非const操作符[]调用const版本是避免代码重复的安全方法。

总结

  • 声明const可以借助编译器检测使用错误。const可以应用于任何作用域的对象、函数参数和返回类型,以及作为一个整体的成员函数。
  • 编译器强制执行位常量,但你应该使用逻辑常量进行编程。
  • 当const和非const成员函数具有本质上相同的实现时,可以通过让非const版本调用const版本来避免代码重复。

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

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

相关文章

MATLAB Sub2ind下标值转化

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 前言 sub2ind([10,10],1,10) 10行10列 网格内第1行 第10列的数值是多少&#xff1f; 10*10的网格第一列 数值为&#xff1a;1 2 3 4 5 6 7 8 9 10&#xff1b…

Unity利用ZXing库 生成和识别二维码

ZXing 创建及识别二维码 生成二维码 目标 能够生成任意大小的二维码生成的二维码可调整背景颜色和码点的颜色生成的二维码中心可带有小Icon生成的二维码可带边框并可调整边框宽度和颜色 实现 using System.Collections.Generic; using UnityEngine; using ZXing; using ZX…

2023了,前端实现AI电子秤思路分析

前景小知识&#xff1a; 这几年ai这个话题非常火爆&#xff0c;笔者从事零售行业软件开发也接到了新需求&#xff0c;希望实现ai电子秤&#xff0c;老规矩&#xff0c;先看需求 举个栗子&#xff1a; 或许&#xff0c;你已经留意到&#xff0c;当你在某些大型超市超市或生鲜类…

spring 基于注解管理bean @Autowired

目录结构&#xff1a; 代码示例&#xff1a; UserContronller.java package com.atguigu.spring6.autowired.controller;import com.atguigu.spring6.autowired.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springfra…

阿里云对象存储OSS外网流出流量异常增多导致费用上升的解决方法

本文介绍在使用阿里云的对象存储 OSS服务过程中&#xff0c;外网流量消耗异常增多并导致异常的费用支出这一情况的问题发现、问题定位与几种不同的问题解决方法。 细细数来&#xff0c;写博客已经有近3的历史了&#xff0c;这成为了一项已经陪伴我大半人生的工作&#xff1b;也…

二十章总结

一.线程简介 二.创建线程 1.继承Thread类 Thread类中常用的两个构造方法如下&#xff1a; public Thread():创建一个新的线程对象。 public Thread(String threadName):创建一个名称为threadName的线程对象。 继承Thread类创建一个新的线程的语法如下&#xff1a; p…

设计模式 简单工厂 工厂方法模式 抽象工厂模式

工厂模式介绍 工厂模式是我们最常用的实例化对象模式了&#xff0c;是用工厂方法代替new操作的一种模式。它是创建型模式。 简单工厂 简单工厂模式是指由一个工厂对象决定创建出哪一种产品类的实例, 但它不属于GOF 23种设计模式 简单工厂适用于工厂类负责创建的对象较少的场景,…

如何在Go中并发运行多个函数

引言 Go语言的一个流行特性是它对并发的一流支持,即一个程序可以同时做多件事。随着计算机从更快地运行单个代码流转向同时运行更多代码流,能够并发地运行代码正在成为编程的重要组成部分。为了让程序运行得更快,程序员需要把程序设计成并发运行,这样程序中并发的每一部分…

mmpose 使用笔记

目录 自己整理的可以跑通的代码&#xff1a; 图片demo&#xff1a; 检测加关键点 自己整理的可以跑通的代码&#xff1a; 最强姿态模型 mmpose 使用实例-CSDN博客 图片demo&#xff1a; python demo/image_demo.py \tests/data/coco/000000000785.jpg \configs/body_2d_k…

AE-制作绚丽的图形通道

目录 1.新建合成命名为四边形 2.在合成中新建纯色层命名为tao 3.在纯色层上添加RG Trapcode –>Tao 效果&#xff0c;设置Segment参数 4. 在合成中添加摄像机 5.设置Tao Repeat Paths 相关参数&#xff0c;并调整摄像机的位置 6.设置Tao的 Material & Lighting 等…

skynet笔记

1、skynet.newservice和skynet.uniqueservice的区别 skynet.newservice&#xff1a; 当调用skynet.newservice时&#xff0c;它会每次都创建一个新的服务实例&#xff0c;即使之前已经存在相同类型的服务实例。这意味着可以同时启动多个相同类型的服务实例&#xff0c;它们之…

基于Springboot的高校教学评价系统的设计与实现(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于Springboot的高校教…

【C++】std::bind与functional函数对象

functional 文章目录 functionalstd::bind使用示例 std::function类模板成员函数使用推导指引(C17 起) std::bind 原型&#xff1a; template< class R, class F, class... Args > constexpr /* 未指定 */ bind( F&& f, Args&&... args );函数模板 std…

如何通过TortoiseGit可视化工具查看Git管理的版本树和信息(工作树变更)内容

一、版本树 黑色直线&#xff1a;master分支和基于master分支拉取基础分支都在这条线上&#xff0c;是一条直线。 其他线条&#xff1a;新开分支一定会增加一条线&#xff0c;但不一定每一条线分别代表一个分支。 注&#xff1a;如果一直是一个人&#xff0c;在同一个本地分支…

(三)Java 基本数据类型

目录 一. 前言 二. 基本数据类型 2.1. char&#xff08;字符型&#xff09; 2.2. byte&#xff08;字节型&#xff09; 2.3. short&#xff08;短整型&#xff09; 2.4. int&#xff08;整型&#xff09; 2.5. long&#xff08;长整型&#xff09; 2.6. float&#xff…

powerbuilder游标的使⽤

在某些PowerBuilder应⽤程序的开发中,您可能根本⽤不到游标这样⼀个对象。因为在其它⼯具开发中很多需⽤游标实现的⼯作,在PowerBuilder中却已有DataWin-dow来代劳了。事实上,DataWindow不仅可以替代游标进⾏从后台数据库查询多条记录的复杂操作,⽽且还远不⽌这些。但是同DataW…

前端如何设置模板参数

1.背景&#xff1a; 最近接到一个需求&#xff0c;在一个类似chatGpt的聊天工具中&#xff0c;要在对话框中设置模板&#xff0c;后端提供了很多模板参数&#xff0c;然后要求将后端返回的特殊字符转成按钮&#xff0c;编辑完成后在相应的位置拼接成字符串。 2.效果&#xff1a…

C++ 类模板

目录 前言 类模板语法 类模板和函数模板的区别 类模板没有自动类型推导的使用方式 类模板在模板参数列表中可以有默认参数 类模板中成员函数创建时机 类模板对象做函数参数 指定传入的类型 参数模板化 整个类模板化 类模板与继承 类模板成员函数类外实现 类模板分…

在Spring Cloud中使用OpenFeign完成从一个微服务上传到另一个微服务中

跨服务上传文件&#xff0c;嘿嘿&#xff0c;来一篇实用性高的&#xff0c;本篇将主要完成在Feign中上传文件到另一个微服务中。步骤如下&#xff1a; 我们需要在服务提供者和服务消费者的项目中添加相应的依赖&#xff1a; 对于服务提供者的项目&#xff0c;你需要添加Sprin…

Redis设计与实现之集合及有序集

目录 一、集合 1、编码的选择 2、编码的切换 3、 字典编码的集合 4、集合命令的实现 5、 求交集算法 6、求并集算法 7、 求差集算法 二、有序集 1、编码的选择 2、编码的转换 3、ZIPLIST 编码的有序集 4、SKIPLIST 编码的有序集 三、如何添加元素到集合或有序集中…