【Effective C++ 读书笔记】条款03: 尽量使用 const
2015-07-06 20:28
543 查看
关键字const多才多艺,变化多端却不高深莫测。
const 修饰指针
面对指针, 你可以指出 指针自身、指针所指物、或者两者都不是 const。
如果关键字 const 出现在星号左边,表示被指物是常量。
(const 出现在类型之后,星号之前 ,同上边两者意义相同)
如果出现在星号 右边,表示指针自身是常量。
如果出现在星号两边,表示被指物和指针两者都是常量。
STL 迭代器系列以指针为根据塑模出来,所以迭代器的作用就像个 T* 指针。
const 面对函数声明时的应用
在一个函数声明式内, const 可以和函数返回值、各参数、函数自身(如果是成员函数)产生关联。
另函数返回一个常量值,往往可以降低因客户错误而造成的意外,而不至于放弃安全性和高效性。
将函数返回值声明成const ,可以省下像是“想要键入 ‘==’却意外键成 ‘=’ 的错误”。
如:
const 成员函数
将 const 实施于成员函数的目的,是为了确认该成员函数可作用于 const 对象(不只是 const 数据成员)身上。
这类成员之所以重要,有以下两个理由:
它们使 class 接口比较容易被理解。因为可以知道哪个函数可以改动对象内容而哪个函数不行。
它们使 “操作 const 对象成为可能”。
真实程序中 const 对象大多用于 passed by pointer-to-cosnt 或 passed by reference-to-const 的传递结果。
【注意:】
non-const operator[] 的返回类型是个 reference to char, 不是 char。如果 operator[] 只是返回一个 char, 下面这样的句子就无法通过编译:
那是因为, 如果函数的返回类型是个内置类型,那么改动函数返回值从来就不合法。纵使合法,c++ 以 by value 返回对象这一事实意味着被改动的其实是 tb.text[0] 的一个副本,不是 tb.text[0]自身,那就不会是你想要的行为。
const 与 mutable:
有如下一个问题:
解决方法:
利用一个与 const 相关的摆动场: mutable。 mutable释放掉 non-static 成员变量的约束。
请记住:
将某些东西声明为 const 可帮助编译器侦测出错误用法。const 可被施加于任何作用于内对象、函数参数、返回值类型、成员函数本体。
编译器强制实施 bitwise constness ,但你编写程序时应该使用”概念上的常量性。“
当const 和 non-const 成员函数有着实质等价的实现时,令non-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 版本可避免代码重复。
相关文章推荐
- C++程序常见的性能调优方式
- malloc/free与new/delete的区别
- C++ Traits技术
- C语言中输入输出重定,freopen()妙用
- C语言程序设计 C语言中的时间函数
- c++中冒号(:)的作用
- 快速排序演示
- C++中vector的排序问题
- C++实现字符串之模式匹配(一)
- c语言基本数据类型
- chapter16test5
- [LeetCode] Summary Ranges
- OJ嘻唰唰之改错题(4)-C++继承
- LeetCode-Power of Two-解题报告
- chapter16test4
- LeetCode-Compare Version Numbers解题报告
- ubuntu下安装eclipse IDE for C/C++ developers
- 一个简单的c++加解密程序
- VC++ 获取系统时间、程序运行时间(精确到秒,毫秒)的五种方法
- C++ 虚函数表解析