【Effective C++ 读书笔记】条款03: 尽量使用 const

原创 2015年07月06日 20:28:08

关键字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 成员函数
    privatechar* 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 成员函数
    privatechar* 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++读书笔记】篇二(条款02~条款04)

条款02:尽量以 const,enum,inline 替换 #define                                                           #...
  • woxiaohahaa
  • woxiaohahaa
  • 2016年05月06日 22:05
  • 936

[More Effective C++]尽量使用C++风格的类型转换

Item M2:尽量使用C++风格的类型转换 1、C不支持一下转换: 1)把一个指向const 对象的指针(pointer-to-const-object)转换成指向const 对象的指针(poin...
  • AlphaGQ
  • AlphaGQ
  • 2017年04月10日 21:27
  • 280

《Effective C++》学习笔记——条款31

《Effective C++》学习笔记——条款31:将文件间的编译依存关系降至最低
  • lx417147512
  • lx417147512
  • 2015年06月15日 13:51
  • 1398

《Effective C++》:条款28-条款29

条款28避免返回handles指向对象内部成分:指的是不能返回对象内部数据/函数的引用、指针等。 条款29为异常安全而努力是值得的:指的是要有异常处理机制,避免发生异常时造成资源泄露等问题。...
  • KangRoger
  • KangRoger
  • 2015年02月19日 19:47
  • 1394

Effective C++ 条款2

尽量以const、enum、inline替换#define首先,大家要明白一个道理。#define是什么,有什么作用。很简单,大家都知道#define实现宏定义,如下代码:#define Flag 1...
  • u011058765
  • u011058765
  • 2015年06月19日 12:06
  • 499

《Effective C++》:条款41-条款42

条款41了解隐式接口和编译期多态 条款42了解typename的双重意义条款
  • KangRoger
  • KangRoger
  • 2015年03月10日 22:13
  • 1243

《Effective C++》:条款44-条款45

条款44将与参数无关的代码抽离templates 条款45运用成员函数模板接受所有兼容类型...
  • KangRoger
  • KangRoger
  • 2015年03月12日 22:01
  • 1508

《Effective C++》资源管理:条款13-条款15

在系统中,资源是有限的,一旦用完必须归还给系统,否则可能会造成资源耗尽或其他问题。例如,动态分配的内存如果用完不释放会造成内存泄漏。 这里说的资源不仅仅是指内存,还包括其他,例如文件描述符、网络连接、...
  • KangRoger
  • KangRoger
  • 2015年01月14日 21:46
  • 1326

effective stl 第19条:理解相等(equality)和等价(equivalence)的区别

#include #include #includeusing namespace std;bool ciStringCompare(const string l, const string r) {...
  • u014110320
  • u014110320
  • 2016年09月20日 23:36
  • 251

Effective Modern C++ 条款23 理解std::move和std::forward

Effective Modern C++ 条款23
  • big_yellow_duck
  • big_yellow_duck
  • 2016年08月30日 17:11
  • 1206
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【Effective C++ 读书笔记】条款03: 尽量使用 const
举报原因:
原因补充:

(最多只允许输入30个字)