• 【Effective C++ 读书笔记】条款03: 尽量使用 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 成员函数
        privatechar* 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 成员函数
        privatechar* 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#_循环[do while,while,for]:[c#入门经典]
    Vs 控件错位 右侧资源管理器文件夹点击也不管用,显示异常
    asp.net core 获取当前请求的url
    在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be
    用orchard core和asp.net core 3.0 快速搭建博客,解决iis 部署https无法登录后台问题
    System.Data.Entity.Core.EntityCommandExecution The data reader is incompatible with the specified
    初探Java设计模式3:行为型模式(策略,观察者等)
    MySQL教程77-CROSS JOIN 交叉连接
    MySQL教程76-HAVING 过滤分组
    MySQL教程75-使用GROUP BY分组查询
  • 原文地址:https://www.cnblogs.com/lanqiu5ge/p/9472209.html
Copyright © 2020-2023  润新知