IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 一起读《Effective C++》: 条款03:尽可能使用const -> 正文阅读

[C++知识库]一起读《Effective C++》: 条款03:尽可能使用const

一起读《Effective C++》: 条款03:尽可能使用const


条款03:尽可能使用const

Use const whenever possible.

1. 定义一个常量指针?指针常量?

条款03 上来直接整一个比较容易记混 的 知识点,使用const来定义 指针和指针所指的变量 为常量:

char greeting[] ="Hello";		
char* p= greeting;		
		
//const 出现在星号 * 左侧,表示被指物是常量;
//const 出现在星号 * 右侧,表示指针自身是常量;

const char* p = greeting;		//non-const pointer, const data
char* const p = greeting;		//const pointer, non-const data
const char* const p = greeting;	//const pointer, const data

记忆的话只要考虑const*的先后问题就行了,
先有const,那就是实际指向的东西为常量;
先有* ,那就是指针是常量。

定义的时候 int等类型关键字的位置倒是没有影响:

void f1(const A* a);
void f2(A const* b);
//他俩等价,都是指向A类型常量的指针

2. STL迭代器与const

STL的迭代器本身就是以指针为范本构造出来的,所以迭代器与const一起使用的时候语法类似指针和const:

const std::vector<int>::interator iter = vec.begin();	//迭代器指向的变量为常量
std::vector<int>::const_interator cIter= vec.begin();	//迭代器为常量

3. 函数返回值与const

让函数的返回值设置成const一般用在操作符重载函数里面:

class Rational {...};	//声明了有个类叫Rational(有理数)

const Rational operator* (const Rational& lhs, const Rational& rhs);	
//重载了*乘积操作符,这个时候最好使用const作为返回值

主要是为了防止以下这种情况发生:

Rational a,b,c;
(a*b) =c;		//用c赋值a*b的值

这种操作有可能是写代码的时候手抖了,这个时候就需要用const来提示你这个写法不对。

4. 成员函数与const

成员函数是const 意味着什么?
是指我成员函数在执行的过程中不改变所在对象的任何一个bit(bit constness)嘛?
还是说这个const成员函数可以修改他所处理的对象内部的一些bits,但是最终并没有改变实质性的内容,客户端也检测不出来这些改变(lobical constness)呢?

bit constness

下面这个例子里面我们的成员函数为const类型,不会改变类中任何一个bit,但是却有可能使得类里的变量在类外面被轻易的改变。(现在这种办法在C++中已经可以被检测出来并且编译报错)

class Text(){
public:
	 Text(const char* c) {ptr=const_cast<char*>(c);}	//const char*转char*
	 
	 //注意这个成员函数加上const之后其他所有的函数都要加上const
	char& operator[](size_t position) const{return ptr[position];}
	
	void print() const{ //被迫加上const
	   	cout<<ptr;
	}
private:
	char* ptr;
}

int main(){
    const Text txt("Text");
    char* char0 = &txt[0];
    *char0='J';
    txt.print();
    return 0;
}

(注释掉*char0=‘J’;之后就可以正常输出)

在这里插入图片描述
这种办法已经可以检测到了,所以大家大概了解就行。

logical constness

修改类为以下代码会报错:error: assignment of member 'Text::textLength' in read-only object,是因为length的时下不是bitwise const,因为textLength 和 lengthIsValid 都可能被修改,事实上这他俩代表的是数据的长度和有效性本来就应该被修改,那这时候咋办?我们引入顶级手法2:使用mutable释放non-static 成员变量的bitwise constness约束。

#include <iostream>
#include <string>
#include <string.h>
using namespace std;

class Text{
public:
    //构造函数
    Text(const char* c) {ptr=const_cast<char*>(c);}	//这里的const_cast作用是为了移除const
	
	//运算符[]重载
	char& operator[](std::size_t position) const{
	    return ptr[position];
	}//注意这个成员函数加上const之后其他所有的函数都要加上const   

	//打印ptr变量
	void print() const{ //被迫加上const
	    cout<<ptr;
	}
	
	size_t length() const;  //字符串长度变量
private:
	char* ptr;          //指向字符串的指针
	size_t textLength;  //最近一次计算的文本Text长度
	bool lengthIsValid; //长度是否有效
};

size_t Text::length() const{
    if(!lengthIsValid){
        textLength=strlen(ptr);		//Error
        lengthIsValid=true;			//Error
    }
    return textLength;
}

int main(){
    const Text txt("Text");
    char* char0 = &txt[0];
    *char0='J';
    txt.print();
    return 0;
}

这个部分会报错:
在这里插入图片描述在这里插入图片描述
顶级手法2:给 tesxtLength和lengthIsValid变量加上mutable前缀就OK了

5. const 和non-const 成员函数的重复问题

mutable也不能解决全部的const难题,诸如下面这个例子中的重复问题:

class Text{
public:
	const char& operator[](size_t position) const {... return text[position];}
	char& operator[](size_t position) {... return text[position];}
	// const 和 non-const函数需要重复,如果其中包含的内容有很多,那就会产生代码膨胀等问题。
};

代码重复会带来的编译时间、维护、代码膨胀的问题(实际上这种代码重复非常常见,就算是一些开源工具的源码都是如此),这个时候我们可以使用cast转型来优化,在non-const里面使用const的函数,并且 使用const_cast 来减少代码重复:

class Text{
public:
	const char& operator[](size_t position) const {...}
	char& operator[](size_t position) { 
	return const_cast<char&>(static_cast<const Text>(*this)[position]);
	}	// 使用static_cast和const_cast
};

这个手法中的 static_cast(*this) 作用是把Text转为const
const_cast<char&>作用是把返回值的const移除。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:26:28  更:2021-07-31 16:28:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/1 18:52:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码