博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【C++】尽可能使用const
阅读量:4184 次
发布时间:2019-05-26

本文共 4071 字,大约阅读时间需要 13 分钟。

指针、迭代器与const的关系

1.  如果关键字出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在星号两边,表示被指物和指针两者都是常量。如果被指物是常量,把 const 写在类型之前或者类型之后、星号之前是一样的。2.  迭代器的作用就像 T* 指针,const 在迭代器前,迭代器不能改变,即声明一个 T* const 指针;const 在迭代器变量前,迭代器所指变量不能变,即声明一个 const T* 指针,需要用 const_iterator。
vector
vec; const vector
::iterator iter = vec.begin(); //iter就像个T* const *iter = 10; //right ++iter; //iter不能变 vector
::const_iterator cIter = vec.begin(); //cIter就像个const T* *cIter = 20; //*cIter 不能变 cIter++; //right

面对函数声明时的const

const与函数返回值

令函数返回一个常量值,往往可以降低因客户错误而造成的意外,而又不至于放弃安全性和高效性。

const与函数参数

除非需要改动参数或者 local 对象,否则将参数声明为 const


const成员函数

目的:确认该成员函数可以作用于const对象身上。

为什么?

1.  使class接口容易被理解,可以得知哪个函数可以改动对象内容而哪个函数不行2.  可以操作const对象,const成员函数可用来处理取得的const对象,也可以操作non-const对象

PS:两个成员函数如果只是常量性不同,那么也可以被重载。

class TextBlock{public:    TextBlock(string str)    {        text = str;    }    const char& operator[] (size_t position) const    {        cout << "call const" << endl;        return text[position];    }    char& operator[] (size_t position)    {        cout << "call non-const" << endl;        return text[position];    }private:    string text;};int main(){    TextBlock tb("Hello");    cout << tb[0] << endl;//调用non-const    tb[0] = 'X';    //right               const TextBlock ctb("World");    cout << ctb[0] << endl;//调用const    //ctb[0] = 'X';  //error 写一个const对象    return 0;

程序输出:

这里写图片描述

还要注意,`non-const operator[]` 返回类型是 `char&`  **如果返回类型是个内置类型,那么改动函数返回值从来就不合法**。即使合法,那么按照pass by value返回,改变的也只是对象的一个副本,而没有改变对象本身。

成员函数是const意味着什么?

两个流行概念:bitwise constnesslogical constness

bitwise constness

是C++对常量性的定义,const成员函数不可以更改对象内任何non-static成员变量。

一个更改了“指针所指物”的成员函数虽然不能算是const,但如果只有指针隶属于对象,而指针所指对象不属于对象,那么称此函数为bitwise constness编译器不会有异议。

using namespace std;class CTextBlock{public:    CTextBlock(const char text[])    {        pText = (char*)malloc(sizeof(char)*strlen(text));        strcpy(pText,text);    }    char& operator[] (size_t position)const    {        return pText[position];    }private:    char *pText;};int main(){    const CTextBlock cctb("Hello");    char* pc = &cctb[0];    *pc = 'J';    cout << cctb[0] << endl;    return 0;}

operator实现代码并不更改pText,编译器认定它是bitwise constness。创建了一个常量对象,并设初值,而且只对它调用const成员函数,但是cctb的成员内容变成了”Jello”,终究还是改变了它的值。

logical constness

一个const成员函数可以修改它所处理的对象内的某些bits,但只有在客户端侦测不出的情况下才得如此。

class CTextBlock{public:    CTextBlock(const char text[])    {        pText = (char*)malloc(sizeof(char)*strlen(text));        strcpy(pText,text);    }    size_t length() const;private:    char *pText;    size_t textLenght;      //最近一次计算的文本区块长度    bool lengthIsValid;     //目前的长度是否有效};size_t CTextBlock::length() const{    if(!lengthIsValid)    {        textLenght = strlen(pText);  //error          lengthIsValid = true;       //在const成员函数内不能给对象成员赋值    }    return textLenght;}

成员函数length()当然不是bitwise const,因为textLengthlengthIsValid都可能被修改。但是编译器坚持认为是bitwise const,因此出现 error。

解决方法:利用C++的一个与 const 相关的摆动场:mutable(可变的)。mutable 释放掉 non-static 成员变量的 bitwise constness 约束。

比如上例中改为:

mutable size_t textLength;mutable bool lengthIsValid;

这样在const成员函数内,这些变量也可被更改。

在const和non-const成员函数中避免代码重复

比如const完全和non-const版本做的工作一样,只是其返回类型多了一个const资格修饰。这时候我们想的是实现这个功能一次并使用两次,也就是说必须令其中一个调用另一个。

那么谁调用谁呢?

const 成员函数调用 non-const 成员函数是一种错误行为,因为对象有可能因此被改动;而反向调用是安全的,non-const成员函数本来就可以对其对象做任何动作,所以在其中调用一个const成员函数并不会带来风险。

还是以 class TextBlock为例:

/* const 和以前一样*/const char& operator[] (size_t position) const    {        ...        ...        ...        return text[position];    }/* non-const 调用 const operator[]*/    char& operator[] (size_t position)    {        return         const_cast
( static_cast
(*this) [position] ); return text[position]; }

两次转型:

1. 将自身*this从原始类型TextBlock&转型为const TextBlock&,使用 static_cast*this加上const
2. 从const operator[]的返回值中移除const,用const_cast

请记住:1.  将某些东西声明为const可帮助编译器侦测出错误用法。const 可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。2.  编译器强制实施bitwise constness,但编写程序时应该使用“概念上的常量性”。3.  当 const 和 non-const 成员函数有着实质等价的实现时,令non-const 版本调用 const 版本可避免代码重复。
你可能感兴趣的文章
CareerCup Pots of gold game:看谁拿的钱多
查看>>
CarreerCup Sort Height
查看>>
CareerCup Sort an array in a special way
查看>>
CareerCup Find lexicographic minimum in a circular array 循环数组字典序
查看>>
CareerCup Cost of cutting wood
查看>>
Find the number of subsets such that the sum of numbers in the subset is a prime number
查看>>
CareerCup Binary Tree the Maximum of 人
查看>>
CareerCup Divide n cakes to k different people
查看>>
CareerCup Randomly return a node in a binary tree
查看>>
CareerCup Given a sorted array which contains scores. Write a program to find occurrence
查看>>
CareerCup The number of pairs (x, y) of distinct elements with condition x + y <= Threshold
查看>>
Build a key-value data structure which can perform lookup and rangeLookup(key1, key2)
查看>>
整数划分问题---动态规划、递归
查看>>
Balanced Partition
查看>>
Number of 1s
查看>>
CareerCup Find all the conflicting appointments from a given list of n appointments.
查看>>
CareerCup Given an array having positive integers, find a subarray which adds to a given number
查看>>
CareerCup Generate all the possible substrings
查看>>
CareerCup Given an array A[], find (i, j) such that A[i] < A[j] and (j - i) is maximum.
查看>>
Brain Teaser 球变色
查看>>