ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

[笔记]Effective C++ 条款3:尽可能使用const

2021-09-07 11:58:15  阅读:157  来源: 互联网

标签:std const Effective C++ operator position data size


T* const 表示不可指向不同的东西 但指向的东西的值可以改变

const T* 表示不可改变指向的东西的值 但可以指向不同的东西

T* const p (const修饰p p为指针 被const修饰后不该被改动 指针p不能改变 但指向的内容*p可被改变)

const T* p (const修饰*p *p为不该被改动的对象)

STL迭代器:

std::vector<int> vec;
const std::vector<int>::iterator iter = vec.begin();	//iter的作用像个T* const 
*iter = 10;	//可以实现,改变的是所指物
++iter;		//错误!iter为const
std::vector<int>::const_iterator cIter= vec.begin();	//cIter的作用像个const T*
*cIter = 10;	//错误!*cIter为const
cIter++;		//可以改变cIter

const成员函数

两个成员函数如果只是常量性(constness)不同,可以被重载。

logical constness,主张一个const成员函数可以修改他所处理的对象内的某些bits,但只有在客户端侦测不出的情况下才得如此。例如CTextBlock class有可能高速缓存(cache)文本区块的长度以便应付询问:

class CTextBlock {
public:
    std::size_t length() const;
private:
    char* pText;
    std::size_t textLength;	//最近一次计算的文本区块长度
    bool lengthIsValid;		//目前的长度是否有效
};
std::size_t CTextBlock::length() const{
    if (!lengthIsValid){
        textLength = std::strlen(pText);	//错误!在const成员函数内不能赋值
        lengthIsValid = true;		//    给textLength和lengthIsValid
    }
    return textLength;
}

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

class CTextBlock {
public:
    std::size_t length() const;
private:
    char* pText;
    mutable std::size_t textLength;	//这些成员变量可能总是会被改变
    mutable bool lengthIsValid;		//即使在const成员函数内
};
std::size_t CTextBlock::length() const{
    if (!lengthIsValid){
        textLength = std::strlen(pText);	//现在这样就可以了
        lengthIsValid = true;		//
    }
    return textLength;
}

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

class TextBlock{
public:
    const char& operator[](std::size_t position) const{
        	//边界检查(bounds checking)
         	//志记数据访问(log access data)
          	//检验数据完整性(verify data integrity)
           return text[position];         		    
    }
    char& operator[](std::size_t position){
           //边界检查(bounds checking)
         	//志记数据访问(log access data)
          	//检验数据完整性(verify data integrity)
           return text[position];
    }
private:
    std::string text;
}

以上有代码重复以及伴随的编译时间、维护、代码膨胀等问题。真正该做的是实现operator[]的机能一次并使用它两次。即在其中一个调用另一个。将常量性转除(casting away constness)

class TextBlock{
public:
    const char& operator[](std::size_t position) const{
        	//边界检查(bounds checking)
         	//志记数据访问(log access data)
          	//检验数据完整性(verify data integrity)
           return text[position];         		    
    }
    char& operator[](std::size_t position){	//现在只调用const op[]
           //边界检查(bounds checking)
         	//志记数据访问(log access data)
          	//检验数据完整性(verify data integrity)
           return 
               const_cast<char&>(				//将op[]返回值的const转除
                    static_cast<const TextBlock&>(*this)    //为*this加上const
                	    [position]	 );		    //调用const op[]
    }
private:
    std::string text;
}

这份代码有两个转型动作。在non-const operator[]内部若只是单纯调用operator[],会递归调用自己。所以必须明确的指出调用的是const operator[],但C++缺乏直接的语法可以这样做。因此这里将*this从原始类型TextBlock&转型为const TextBlock&。所以这里有两次转型:第一次用来为*this添加const(这使接下来调用operator[]时得以调用const版本),第二次从const operator[]的返回值中移除const。

反向做法(const成员函数调用non-const成员函数)是错误行为:因为对象有可能因此被改动。

  1. 将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。
  2. 编译器强制实施bitwise constness,但编写程序时应该使用“概念上的常量性”(conceptual constness)。
  3. 当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复。

标签:std,const,Effective,C++,operator,position,data,size
来源: https://blog.csdn.net/weixin_42796916/article/details/120155113

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有