【Effective C++ 读书笔记】条款03: 尽量使用 const
关键字const多才多艺,变化多端却不高深莫测。
const 修饰指针 
面对指针, 你可以指出 指针自身、指针所指物、或者两者都不是 const。
如果关键字 const 出现在星号左边,表示被指物是常量。 
(const 出现在类型之后,星号之前 ,同上边两者意义相同) 
如果出现在星号 右边,表示指针自身是常量。 
如果出现在星号两边,表示被指物和指针两者都是常量。
char greeting[ = "hello";
char* p = greeting; //non-const pointer, non-const data
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
STL 迭代器系列以指针为根据塑模出来,所以迭代器的作用就像个 T* 指针。
std::vector<int> vec;
const std::vector<int>::iterator iter = vec.begin();//iter 的作用像个 T* const
*iter = 10;     //没问题,改变iter所指物
++ iter;        //错误! iter 是const
std::vector<int>::const_iterator cIter = vec.begin();//cIter 的作用像个 const T*
*cIter = 10;    //错误! *cIter 是 const
++ cIter;   //没问题, 改变 cIter 
const 面对函数声明时的应用 
在一个函数声明式内, const 可以和函数返回值、各参数、函数自身(如果是成员函数)产生关联。
另函数返回一个常量值,往往可以降低因客户错误而造成的意外,而不至于放弃安全性和高效性。
将函数返回值声明成const ,可以省下像是“想要键入 ‘==’却意外键成 ‘=’ 的错误”。 
如:
class Rational {};
const Rational operator* (const Rational& lhs, cosnt Rational& rhs);
//将返回值声明成const可以避免以下暴行
Rational a, b, c;
(a * b) = c;
if(a * b = c) ... //打字错误造成的隐式错误
const 成员函数 
将 const 实施于成员函数的目的,是为了确认该成员函数可作用于 const 对象(不只是 const 数据成员)身上。 
这类成员之所以重要,有以下两个理由:
- 它们使 class 接口比较容易被理解。因为可以知道哪个函数可以改动对象内容而哪个函数不行。
 - 它们使 “操作 const 对象成为可能”。
 
真实程序中 const 对象大多用于 passed by pointer-to-cosnt 或 passed by reference-to-const 的传递结果。
class TextBlock{
public:
    //operator[] for const 对象
    const char& operator[](std::size_t position) const
    { return text[position]; }
    //operator[] for non-const 对象
    char& operator[](std::size_t position)
    { return text[position]; }
private:
    std::string text;
}
TextBlock 的 operator[]可以被这样使用:
TextBlock tb("hello");
std::cout << tb[0] << endl;//调用 non-const TextBlock::operator[]
const TextBlock ctb("World!!");
std::cout << ctb[0]; //调用 const TextBlock::operator[] 
void print(const TextBlocks& ctb)   //此函数中ctb是const
{
    std::cout << ctb[0]; //调用 const TextBlock::operator[]
}
【注意:】 
non-const operator[] 的返回类型是个 reference to char, 不是 char。如果 operator[] 只是返回一个 char, 下面这样的句子就无法通过编译:
tb[0] = 'x';
那是因为, 如果函数的返回类型是个内置类型,那么改动函数返回值从来就不合法。纵使合法,c++ 以 by value 返回对象这一事实意味着被改动的其实是 tb.text[0] 的一个副本,不是 tb.text[0]自身,那就不会是你想要的行为。
const 与 mutable:
有如下一个问题:
class cTextBlock{
    public:
        std::size_t length() const; //cosnt 成员函数
    private:
        char* pText;
        std:size_t textLength;
        bool lengthIsValid;
}
    std::size_t cTextBlock::length() const
    {
        if(!lengthIsValid)
        {
            textLength = std::strlen(pText); //错误! 在 const 成员函数内不能赋值给 textLength 和 lengthIsValid
            lengthIsValid = true;
        }
        return textLength;
    }
};
解决方法: 
利用一个与 const 相关的摆动场: mutable。 mutable释放掉 non-static 成员变量的约束。
//mutable 释放掉 const 约束(non-static 成员)
class cTextBlock{
    public:
        std::size_t length() const; //cosnt 成员函数
    private:
        char* pText;
        mutable std:size_t textLength;  //这些成员变量可能总会被更改,即使在 const 成员函数内
        mutable bool lengthIsValid;
}
std::size_t cTextBlock::length() const
{
    if(!lengthIsValid)
    {
        textLength = std::strlen(pText); //now is ok
        lengthIsValid = true;
    }
    return textLength;
}
};
请记住:
- 将某些东西声明为 const 可帮助编译器侦测出错误用法。const 可被施加于任何作用于内对象、函数参数、返回值类型、成员函数本体。
 - 编译器强制实施 bitwise constness ,但你编写程序时应该使用”概念上的常量性。“
 - 当const 和 non-const 成员函数有着实质等价的实现时,令non-const版本调用const 版本可避免代码重复。
 
【Effective C++ 读书笔记】条款03: 尽量使用 const的更多相关文章
- 《Effective C++》读书笔记 条款02 尽量以const,enum,inline替换#define
		
Effective C++在此条款中总结出两个结论 1.对于单纯常量,最好以const对象或enum替换#define 2.对于形似函数的宏,最好改用inline函数替换#define 接下来我们进行 ...
 - 《Effective C++》读书笔记 条款03 尽可能使用const 使代码更加健壮
		
如果你对const足够了解,只需记住以下结论即可: 将某些东西声明为const可帮助编译器侦测出错误用法,const可被施加于任何作用于内的对象.函数参数.函数返回类型.成员函数本体. 编译器强制实施 ...
 - effective C++ 读书笔记  条款08
		
条款08 别让异常逃离析构函数: 假设在析构函数其中发生了异常,程序可能会过早结束或者导致不明白行为(异常从析构函数传播出去) 看代码: #include <iostream> usin ...
 - effective C++ 读书笔记 条款11
		
条款11: 在operator= 中处理"自我赋值" 在实现operator=时考虑自我赋值是必要的就像 x=y .我们不知道变量x与y代表的值是否为同一个值(把x和y说成是一个指 ...
 - effective C++ 读书笔记 条款14 以对象管理资源
		
如果我们使用一个投资行为的程序库: #include "stdafx.h" #include <iostream> #include <memory> us ...
 - Effective STL 读书笔记
		
Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...
 - Effective STL读书笔记
		
Effective STL 读书笔记 本篇文字用于总结在阅读<Effective STL>时的笔记心得,只记录书上描写的,但自己尚未熟练掌握的知识点,不记录通用.常识类的知识点. STL按 ...
 - 【Effective C++ 读书笔记】条款02: 尽量以 const, enum, inline 替换 #define
		
条款02: 尽量以 const, enum, inline 替换 #define 这个条款或许可以改为“宁可以编译器替换预处理器”. 编译过程: .c文件--预处理-->.i文件--编译--&g ...
 - 《Effective C++ 》学习笔记——条款03
		
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
 - Effective C++学习笔记 条款02:尽量以const,enum,inline替换 #define
		
尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...
 
随机推荐
- StreamWrite类
			
FileStream类,该对象只能以字节形式读取/写入数据,这就使得操作非常困难. 一般有了FileStream对象,都会借用StreamWrite对象或StreamReader对象的方法来处理文件. ...
 - Objective-C #define 用法解析 (转)
			
原文地址: http://blog.csdn.net/kindazrael/article/details/8108868 Objective-C : #define 用法解析 在 C 语言中,预处理 ...
 - python-gearman使用
			
yum -y install gearmand chkconfig gearmand on && /etc/init.d/gearmand start # /etc/sysconfig ...
 - windows10下 Jupyter 添加anaconda环境
			
参考:https://blog.csdn.net/weixin_39934500/article/details/79138235 首先查看 anaconda下的环境信息 conda env lis ...
 - Element-ui安装与使用(网站快速成型工具)
			
我之所以将Element归类为Vue.js,其主要原因是Element是(饿了么团队)基于MVVM框架Vue开源出来的一套前端ui组件.我最爱的就是它的布局容器!!! 下面进入正题: 1.Elemen ...
 - 【2017-06-17】QtGui基础控件:QSpinBox及QDoubleSpinBox
			
今天开始一个新的系列,主要是翻译并摘录QtGui中基础空间的常用方法,并做一些简单的实验程序: 我觉得这是一个炒冷饭的行为,但有时候冷饭不能不炒,不热不好吃,而且也很容易发霉. 其实到现在这种状态,对 ...
 - 22 Swap Nodes in Pairs
			
Given a linked list, swap every two adjacent nodes and return its head. For example,Given 1->2-&g ...
 - Oracle 日期加减运算
			
-- Start 我们都知道数字可以进行加.减.乘.除等运算.那么,日期可不可以呢?答案是,日期只能进行加.减运算. 在开始操作日期之前,我们先了解一下 Oracle 支持哪些日期数据类型,如下所示: ...
 - 并查集,是否成树,Poj(1308)
			
思路: 对于每一条新的边的两个端点,是否是属于一颗树,要是的话,就不是一颗树.否则,就合并. 这里要注意的是,不能是森林,我这里WA了两次了.只不过在最后,查看每个节点的祖先是否是同一个就可以了. # ...
 - jenkins 执行shell命令出错command not found 和No such file or directory
			
[root@localhost usr]# sh test.sh command not found -bash: cd: usr: No such file or directory 这里碰到了一个 ...