zoukankan      html  css  js  c++  java
  • 尽可能使用const

    1、const用于定义常量

    编译器可以对其进行静态数据类型检查

    2、const可用于修饰形式参数

    若你在编写函数时,并没有打算改变参数,这是就应该将参数的类型设置为const reference,这样既可以保证参数的常量性,又提高了传值的效率

    3、const修饰返回值

        若函数的返回值时const pointer,则返回值不可被直接修改,而且返回值必须赋值给const同种类型

        令函数返回一个常量值,该const为顶层const,编译器会直接忽视其作用,但有时会降低因用户的错误而造成的意外

    1 class Rational {};
    2 const Rational operator*(const Rational& lhs, const Rational& rhs);
    3 
    4 Rational a, b, c;
    5 
    6 (a * b) = c;        //编译错误
    7 if ((a * b) = c)    //编译错误

    4、const成员函数

    可以保证该成员函数可以作用于const对象身上

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

    bitwise constness

      成员函数只有在不更改对象的非静态成员变量时才可以说是const,即不更改对象内的任何一个bit,但是有一种特殊情况,类的数据成员为指针,改变指针所指之物并不会改变对象的常量性,可以通过bitwise constness测试

    logical constness

      类中的某些数据成员的变化并不会影响对象的常量性,而将这些数据成员设为mutable

      mutable可以释放掉non-static成员变量的bitwiss constness约束

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

    例如下面的例子

     1 class TextBlock {
     2 public:
     3     const char &operator[](std::size_t position) const {
     4         ......;    //边界检查(bounds checking)
     5         ......;    //日志数据访问(log access data)
     6         ......;    //检验数据的完整性(verify data integrity)
     7         return text[position];
     8     }
     9 
    10     char &operator[](std::size_t position) {
    11         ......;    //边界检查(bounds checking)
    12         ......;    //日志数据访问(log access data)
    13         ......;    //检验数据的完整性(verify data integrity)
    14         return text[position];
    15     }
    16 private:
    17     std::string text;
    18 };

     在上面的例子中,两个都是下标运算符的重载,只是一个函数是const,作用于const对象,一个函数是non-const,作用于non-const对象,其他实现细节相同,会导致大量的代码重复。有人会说,我可以将边界检查,日志数据访问和检验数据的完整性写成三个private函数,提供给这两个下标运算符重载函数的使用,但是这样并不会解决代码重复的问题,你还是重复了一些代码,例如函数的调用,两次return语句等。你需要做的是实现一次operator[]功能,并使用它两次,也就是说,你必须令其中一个调用另一个。

    你无法使用const operator[]函数去调用non-const operator[]函数,因为const operator[]函数可以保证调用对象的bitwess constness,也就是说const对象可以放心调用,但是const operator[]去调用non-const operator[]来避免代码的重复性,这样const operator[]就不会保证调用者的常量性,也就失去了const函数的本质,编译器是不允许的。你的做法也只能用non-const operator[]去调用const operator[],详情请看下面

     1 class TextBlock
     2 {
     3 public:
     4     const char &operator[](std::size_t position) const {
     5         ......;    //边界检查(bounds checking)
     6         ......;    //日志数据访问(log access data)
     7         ......;    //检验数据的完整性(verify data integrity)
     8         return text[position];
     9     }
    10 
    11     char &operator[](std::size_t position) {
    12         return const_cast<char&>(
    13                   static_cast<const TextBlock&>(*this)
    14                            [position]);
    15     }
    16 private:
    17     std::string text; 
    18 };

    当你用const TextBlock对象去调用下标运算符时,调用的是const版本的operator[];当你使用non-const TextBlock对象去调用下标运算符时,调用的是non-const版本的operator[]

    在non-const 版本的operator中,首先将调用的对象强制转换成const对象,以避免重复递归调用自己,当调用完const版本的operator[]时,返回的是const char的引用,此时const char的引用指向的char对象本身并不是const,所以你可以用const_cast将其const去掉。

  • 相关阅读:
    消息队列 RPC之间的区别与联系
    RabbitMQ, ZeroMQ, Kafka 是一个层级的东西吗, 相互之间有哪些优缺点?
    嵌入式软件开发工程师谈软件架构的设计
    值得推荐的C/C++框架和库 (真的很强大)
    10.2-嵌入式系统库资源集合
    正则表达式
    vscode代码阅读
    vscode配置
    VSCode的开发环境zsESampleLinux
    MySQL与宿主Linux之间交互式执行命令
  • 原文地址:https://www.cnblogs.com/swenwen/p/12527181.html
Copyright © 2011-2022 走看看