effect C++ 尽可能使用const
来源:互联网 发布:office2016for mac安装 编辑:程序博客网 时间:2024/05/17 06:48
const 可以指定一个不能被改动的对象
使用const在class外部修饰global或namespace作用域中的常量,或修饰文件、函数、或区域作用域中被声明为static的对象。也可以修饰classes内部的static和non-static成员变量。面对指针,也可以支出指针自身、指针所指物,或者两者都是(或不是)const。
char greeting[]="Hello";char *p =greeting; //non-const pointer,non-const dataconst char *p =greeting; //non-const pointer,const datachar *const p =greeting; //const pointer , non-const dataconst char *const p =greeting; // const pointer, const data关键字const 出现在*左边,表示被指物是常量, 出现在* 右边,表示指针自身是常量;如果出现在两边,表示两者均为常量。
const_iterator
STL迭代器系以指针为根据塑造模出来,所有迭代器的作用就像一个*T指针。声明迭代器为const就像声明指针为const一样(声明一个T* const指针),表明这个迭代器不得指向不同的东西,但它所指的东西的值是可以改变的。
如果希望迭代器所指的东西不可被改动,则需要const_iterator
std:: vector<int>vec...const std ::vector <int>::iterator iter = vector.begin(); //iter 的作用像个 T* const *iter=10; // 没问题 , 改变iter所指物 ++iter; // 错误 !! iter 是conststd::vector <int>::const_iterator cIter=vec.begin(); //cIter 的作用像个 const *T*cIter = 10; // 错误!! *cIter 是const++cIter; // 没问题 改变cIter
const最具威力的用法是面对函数声明时的应用。在一个函数声明式内,const可以和函数返回值、各参数、函数自身(成员函数)产生关联。
const 令函数返回一个常量值
operator*声明式class Radional{....}const Rational operator *(const Rationl &lhs , const Rational &rhs);返回一个const对象可以降低因客户错误而造成的意外,又不至于放弃安全性和高效性
可以避免以下两种情况
Rational a,b,c( a * b ) = c; // 在a * b 的成果上调用 operator =if(a * b = c ); // 其实是 想使用 == 进行比较 导致的错误
const 成员函数将const实施于成员函数的目的,是为了确认该成员函数可作用于const对象身上。 它们使class接口比较容易被理解并使“操作const对象”成为可能。
两个成员函数如果只是常量性不同,可以被重载。
class TextBlock{public:...const char& operator[](std::size_t position)const // operator [] for const对象{return text[position];} char& operator[](std::size_t position) // operator[] for non-const 对象{return text[position];}private: std::string text;}TextBlock 的两个operator[] 可以被这么使用TextBlock tb("Hello");std::cout<<tb[0];const TextBlock ctb("World");std::cout<<ctb[0];实际一点的运用void print (const TextBlock&ctb){ std::cout<<ctb[0]; //调用const TextBlock::operator[]}只要重载operator[]并对不同的版本给予不同的返回类型,就可以令const和non-const TextBlocks 获得不同的处理:std::cout<<tb[0]; //读一个 non-const TextBlocktb[0]='x'; //写一个 non-const TextBlockstd::cout<<ctb[0]; //读一个 const TextBlockctb[0]='x'; // 错误!!! 写一个const TextBlock
bitwise constness
成员只有在不更改对象之任何成员变量(static除外)时才可以说是const。也就是说它不更改对象内的任何一个bit。这种论点的好处是很容易侦测违反点:编译器只需要寻找成员变量的复制动作即可。const成员函数不可以更改对象内任何non-static 成员变量。
一个更改了“指针所指物”的成员函数虽然不能算是const,但如果只有指针(而非所指物)隶属于对象,那么此函数为bitwise不会引发编译器异议。
class CTextBlock{public:... char &operator[](std::size_t position)const{return pText[position];}private: char *pText;};
此代码,operator[] 实现代码并不更改pText。但是const CTextBlock cctb("Hello"); //声明一个常量对象char *pc = &cctb[0]; // 调用const operator[]取得一个指针,指向cctb的数据。*pc = 'J' // 更改了 const
logical constness
一个const成员函数可以修改它所处理的对象内的某些bits,但只有在客户端侦测不出的情况下才得如此。例如:CTextBlock class 有可能高速缓存文本区块的长度以便应付询问:
class CTextBlock{public: ... std::size_t length() const;private: char *pText; std::size_t textLength; //最近一次计算的文本区块长度 bool lengthIsValid; // 目前的长度是否有效};std::size_t CTextBloock::length()const{ if(!lengthisValid) { textLength = std :: strlen(pText); //错误!! 在const成员函数内不能给 textLenght 和 lengthIsValid 赋值 lengthIsValid = true; //将成员成员函数声明为const,则该函数不允许修改类的数据成员 } return textLength;}因为textLength和lengthIsValue都可能被修改,对const CTextBlock对象而言虽然可以接受,但是编译器不同意。解决:使用mutable
class CTextBlock{public: ... std::size_t length() const;private: char *pText;mutable std::size_t textLength; //最近一次计算的文本区块长度mutable bool lengthIsValid; // 目前的长度是否有效};std::size_t CTextBloock::length()const{ if(!lengthisValid) { textLength = std :: strlen(pText); //错误!! 在const成员函数内不能给 textLenght 和 lengthIsValid 赋值 lengthIsValid = true; } return textLength;}
在non-const 和const 之间避免重复
如果operator[] 里不单只是返回一个引用指向字符,也执行边界检验,志记访问信息,甚至数据完善完善性检验。把这些同时放进const 和non-const operator[]中,会产生如下代码
class TextBlock{public : ... const char& operator[](std ::size_t position) const { .... //边界检验 .... //志记数据访问 .... //检验数据完整性 return text[position]; } char & operator[](std::size_t position){ ... //边界检验 ... //志记数据访问 ... //检验数据完整性 return text[position];} private: std::string text;};
以上重复了一些代码,真正应该实现的是实现operator[]的机能一次,并使用它两次。必须使其中一个调用另一个。
const operator[]完全做掉了 non-const版本中该做的一切,唯一的不同是返回类型多了一个const资格修饰。这种情况如果将返回值的const转除是安全的,因为
不论谁调用non-const operator[]都一定有个non-const对象,否则就不能调用non-const函数。所有在non-const中调用const可以避免代码重复。
class TextBlock{public : ... const char& operator[](std ::size_t position) const { .... //边界检验 .... //志记数据访问 .... //检验数据完整性 return text[position]; } char & operator[](std::size_t position){ return const_cast<char&>static_cast<const TextBlock&>(*this)[positon];} private: std::string text;};
让non-constoperator[] 调用其const兄弟,但non-const operator[]内部只是单纯调用operator[],会递归调用自己,必须明确指明调用的是const operator[] ,因此将*this从其原始类型TextBlock& 转型为const TextBlock&。所以这里有两次转型:第一次用来为*this 添加const 使operator[]调用const版本(static_cast),第二次从const operator [] 中移除const(const_cast)const成员函数承诺绝不改变其对象的逻辑状态,non-const吗没有。所以 令const调用non-const 就冒了这个风险:承诺不改动的对象被改动了。non-const成员函数本来就可以对其对象做任何动作,所以调用一个const成员函数并不会有太大的风险。
将某些东西声明为const可帮助编译器侦测出错误用法,const可施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。
编译器强制实行biwise constness ,但编写程序时应使用“概念上的常量性”(conceptual constness)
当const和non-const 成员函数有着实质等价的实现时,令non-const 版本调用 const版本可避免代码重复。
- effect C++ 尽可能使用const
- 《Effect C++》学习------条款03:尽可能使用const
- 【C++】尽可能使用const
- effective c++:条款21: 尽可能使用const
- 【Effective C++】条款03-尽可能使用const
- Effective C++:条款03:尽可能使用const
- [Effective C++]条款03:尽可能使用const
- Effective C++——尽可能使用const
- Effective C++--条款03:尽可能使用const
- 尽可能地使用const
- 尽可能使用 const
- 尽可能使用 const
- 尽可能使用const
- item3: 尽可能使用const
- 3、尽可能使用const
- 尽可能使用 const
- 尽可能使用const
- 尽可能使用const
- ubuntu + nohup
- CI-搭建
- jquery $.getScript优缺点
- java反射机制中的getDeclaredField()
- 数据库内外网交换怎么做的,如果交换给你做,你怎么做
- effect C++ 尽可能使用const
- java中的位运算
- React+webpack开发环境的搭建_0
- unity 如何去除打包好的应用程序边框
- Mybatis分页查询及底部页码实现
- C++模板:函数模板、类模板、模板与继承
- 对原始信源的格式、存储形式及表示形式的详解
- JAX-WS 报错 Unable to create JAXBContext
- android listview去掉分割线 && 去除或替换listview 默认的点击选中时的颜色