`
kanwoerzi
  • 浏览: 1635633 次
文章分类
社区版块
存档分类
最新评论

Effective C++学习笔记——条款03:尽可能使用const

 
阅读更多

const 多才多艺,可以用在classes外部修饰global和namespace 作用域中的常量。或修饰文件、函数、或区块作用域中被声明的为static的对象。还可以修饰classes内部的static和non-static成员变量,面对指针,你也可以指出指针自身、指针所指物,或两者都是const:如下代码:


如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在星号两边,表示被指物和指针两者都是常量。关键字const写在类型之前与之后意义相同。

常量意味着是不可以改变的。

另外在在使用指针的时候,const只要在*号之前,那么表达的都是指针所指的对象都是常量。比如代码:

在讲解STL迭代器之前,先复习一下C++pirmer的内容,如下:

那么我就来给大家说一下在C++ PRIMER (第四版)中讲解的。进行比较

如果指针指向了const对象,则不允许用指针来改变其所指的const值,为了保证这个特性,c++语言强制要求指向const对象的指针也必须具有const特性。

const double * cptr;//cptr may point to a double thatis const

这里,的cptr是一个指向double类型const对象的指针,const先顶了cptr指针所指的对象类型,而并非cptr本身。即是cptr本身并不是const,再定义时候并不需要对它进行初始化,如果需要的话,可以给cptr重新赋值。使其指向另一个const对象。但不能通过cptr修改所指对象的值。

这样就是错的,*cptr=42;

把一个const对象的地址赋给一个普通的。非const对象的指针也会导致编译时的错误。

在讲解STL迭代器之前,先复习一下C++pirmer的内容,如下:

那么我就来给大家说一下在C++ PRIMER (第四版)中讲解的。进行比较

如果指针指向了const对象,则不允许用指针来改变其所指的const值,为了保证这个特性,c++语言强制要求指向const对象的指针也必须具有const特性。


这里,的cptr是一个指向double类型const对象的指针,const先顶了cptr指针所指的对象类型,而并非cptr本身。即是cptr本身并不是const,再定义时候并不需要对它进行初始化,如果需要的话,可以给cptr重新赋值。使其指向另一个const对象。但不能通过cptr修改所指对象的值。

这样就是错的,

*cptr=42;

把一个const对象的地址赋给一个普通的。非const对象的指针也会导致编译时的错误。

编译器报的错误是:

但是可以把非const对象的地址赋给指向const对象的指针。

现在回到Effective C++中,指出STL迭代器洗衣指针为根据塑摸出来,所以迭代器的作用就像个T*指针,声明迭代器为const就行声明指针为const一样。表示这个迭代器不得指向不同的东西,就是指针的值不可以改变,但是所指向的值是可以改动的。如果你希望迭代器所指向的东西不可被改动,你需要的是一个const_iterator:

如下所示代码:


这两个迭代器const修饰的对象不一样,iterator修饰的是指针为常量,不能对指针值修改,const_iterator为const修饰的是指针所指的对像不能改变。

const最具威力的用法是在函数声明时的应用。一个函数声明式内,const可以和函数返回值、各参数、函数自身(如果是成员函数)产生关联。令函数返回一个常量值,可以降低因客户错误而造成的意外,而又不至于放弃安全性和高效性。有理数的operator*声明式:

下面有如下代码:

报的错误是:

1>d:\workspace\visual studio 2005\projects\useconst\useconst\useconst.cpp(32) : error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const Point' (or there is no acceptable conversion)

就如以上暴行一样。如书上所述

如果a和b是内置类型,这样的代码直截了当就是不合法。一个“良好的用户自定义类型”的特征是它们避免无端地与内置类型不兼容,因此允许对两值乘积做赋值动作也就没有什么意思。将operator*的回传值声明为const可以预防那个“没意思的赋值动作”,这就是该那么做的原因。

至于const参数,没有什么特别新颖的观念,不过像local const对象一样,你应该在必要使用的时候使用它们。除非你有需要改动的参数或local对象,否则请将它们声明为const。只不过多打6个字,却省下恼人的错误,像是“想要键入‘==’却意外键成‘=’”的错误,一如稍早所述。

const成员函数

将const实施于成员函数的目的,是为了确认该成员函数可用于对const对象身上。这类成员函数重要的两个理由:第一,它们使class接口比较容易理解,得知哪个函数可以改动对象内容而哪个不行,很是重要。第二,使“操作const对象”成为可能。这对编写高效代码是个关键,如条款20所言,改善C++程序效率的一个根本办法是以pass by reference-to-const方式传递对象,而此技术可行的前提是,我们有const成员函数可用来处理取得(并经修饰而成)的const对象。

许多人漠视一件事实:两个成员函数如果只是常量性(constness)不同,可以被重载。这是在是一个重要的C++特性。考虑以下class,用来表现一大块文字:


只要重载operator[]并对不同的版本给予不同的返回类型,就可以令const和non-const TextBlocks获得不同的处理:那么以下代码错误的原因就是


还有我觉得比较重要一点就是:non-const operator[]的返回类型是个reference to char,不是char。如果operator[]只是返回一个char,下面句子是不能编译的:

tb[0]='x';

这是因为,如果函数的返回类型是个内置类型,那么改动函数返回值从来就不是合法的。即使合法,改动的是其副本,不是值本身。

}

许多情况即使成员函数不具备const性质却依然可以通过编译器的测试。以上面TextBlock的 const char& operator[](size_tpostion) const为例,看下面代码的操作。它本身是bitwise constiness,但是它返回的char&却可以修改内部的值,完全违背了bitwise的概念。
TextBlock str("String");
str[0] = ‘A’;
还有假设这样的情况,TextBlock 需要返回字符串的长度。只有调用ReGetLength方法才会重新计算获得当前的字符长度,而在const下,是不允许修改_length的值。但对于客户端来说这应该是个const,无论内部是否重新进行计算。

length的实现当然不是bitwise const,因为textLength和lengthIsValid都可能被修改。这两笔数据被修改对const CTextBlock对象而言虽然可以接受,但编译器不同意。它们坚持bitwise constness,怎么办?解决方法很简单:利用C++的一个与const相关的摆动场:mutable(可变的)。mutable释放掉non-static成员变量的bitwise constness约束:

总结一下几点:

1.将某些东西声明为const可帮助编译器侦测出错误用法.const可被施加于任何作用域的对象,函数参数,函数返回类型,成员函数本体.

2.编译器强制实施bitwise constness,但你编写程序时应该使用"概念上的常量性"(conceptual constness);

3.当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复

分享到:
评论

相关推荐

    Effective C++ 中文版

    条款03:尽可能使用const 条款04:确定对象被使用前已先被初始化 2.构造/析构/赋值运算 条款05:了解C++默默编写并调用哪些函数 条款06:若不想使用编译器自动成生的函数,就该明确拒绝 条款07:为多态基类声明...

    Effective C++

    条款21:尽可能使用CONST 条款22:尽量用传引用而不用传值 条款23:必须返回一个对象时不要试图返回一个引用 条款24:在函数重载与设定参数默认值间慎重选择 条款25:避免对指针与数字类型的重载 条款26:当心潜在的二义性...

    EFFECTIVE C++ 条款03 尽量使用const 思维导图

    EFFECTIVE C++ 条款03 尽量使用const 思维导图

    Effective.C++.中文第二版.50条款doc文档.chm

    条款21: 尽可能使用const 条款22: 尽量用“传引用”而不用“传值” 条款23: 必须返回一个对象时不要试图返回一个引用 条款24: 在函数重载和设定参数缺省值间慎重选择 条款25: 避免对指针和数字类型重载 条款26: 当心...

    exceptional c++:47个c++工程难题、编程问题和解决方案(英文版)

    《exceptional c++:47个c++工程难题、编程问题和解决方案(中文版)》...条款43:正确使用const 222 条款44:类型转换 231 条款45:bool 238 条款46:转调函数 242 条款47:控制流程 244 后记 254 参考书目 256

    Effective C++(第三版)

    条款03:尽可能使用const use const whenever possible. 条款04:确定对象被使用前已先被初始化 make sure that objects are initialized before they're used. 2. 构造/析构/赋值运算 constructors, destructors, ...

    Effective_C++_笔记

    1.2 条款02:尽量以const,enum,inline替换#define 这个条款或许可以改为“宁可用编译器替换预处理器”。 通常C++要求你对所使用的任何东西提供一个定义式,但如果它是个class专属常量 又是static且为整数类型...

    EffectiveC++终稿44__tagged_2019-06241

    目 录一.让自己习惯 C++ 1条款 03:尽可能使用 const 23)const 修饰成员函数 2条款 04:确定对象被使用前已先被初始化 4二.构造/析构

    信息奥赛c++学习笔记——贪心算法

    一,算法 在当前状态下找出局部最优解,转化为全局最优解。 二,活动安排问题 1.问题描述:给定n个开区间(ai,bi),在给定范围内尽量选择多个区间...(const qing &x)const{ return b>n; for(int i=1;i<=n;i++){

    C++:关于const的思考.doc

    C++:关于const的思考.doc onst的思考 1、什么是const? 常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。(当然,我们可以偷梁换柱进行更新:) 2、为什么引入const?  const...

    Effective STL(中文)

    <br>《Effective STL》目录: <br>前言 致谢 导读 容器 条款1:仔细选择你的容器 条款2:小心对“容器无关代码”的幻想 条款3:使容器里对象的拷贝操作轻量而正确 条款4:用empty来代替...

    effective stl 中文 pdf

    条款26: 尽量使用iterator代替const_iterator,reverse_iterator和const_reverse_iterator 条款27: 使用distance和advance把const_iterators转化成iterators 条款28: 了解如何通过reverse_iterator的base得到...

    effective stl stl 技巧

    条款6:警惕C++最令人恼怒的解析 条款7:当使用new得指针的容器时,记得在销毁容器前delete那些指针 条款8:永不建立auto_ptr的容器 条款9:在删除选项中仔细选择 条款10:注意分配器的协定和约束 条款11:...

    C++中const使用说明

    C++中const使用说明。。。C++中const使用说明。。。

    CUJ:标准库:定义iterator和const iterator.docx

    CUJ:标准库:定义iterator和const iterator

    Effective Modern C++ 原版pdf by Meyers

    If you’re an experienced C++ programmer and are anything like me, you initially approached C++11 thinking, “Yes, yes, I get it. It’s C++, only more so.” But as you learned more, you were surprised...

    C++学习笔记、常见面试知识点.zip

    C++学习笔记和常见面试知识点,C++11特性,包括多态、虚表、移动语义、友元函数、符号重载、完美转发、智能指针、const和static、数组指针和指针数组、struct内存对齐、enum和union关键字等等。帮助了解C++的特性,...

    Effictive STL CHM中文版

    条款26: 尽量使用iterator代替const_iterator,reverse_iterator和const_reverse_iterator 条款27: 使用distance和advance把const_iterators转化成iterators 条款28: 了解如何通过reverse_iterator的base得到...

    徐彤教程-C++编程const与static第0263讲:实例03-const成员函数

    徐彤老师耗时三年倾心制作,专业录制,通俗,细致的讲解了C++ 编程从入门到高级

    徐彤教程-C++编程const与static第0262讲:实例03-const成员变量

    徐彤老师耗时三年倾心制作,专业录制,通俗,细致的讲解了C++ 编程从入门到高级

Global site tag (gtag.js) - Google Analytics