首页 > 编程语言 >C++基础/限定符及一些关键字在限定函数的作用

C++基础/限定符及一些关键字在限定函数的作用

时间:2024-08-24 21:15:31浏览次数:9  
标签:const 右值 int void 左值 C++ 关键字 volatile 限定符

在学习中发现对const在限定函数的作用有些模糊,以下为笔者的学习总结

1.5cv限定符及一些关键字在限定函数的作用

  1. c(const)v(volatile)

    • const:用于表示该函数不会改变类的成员变量,所以是可以修改全局变量的

    • volatile:用于告诉编译器该对象可能会被程序外部修改

      #include <iostream>
      #include <string>
      
      int year = 2023; // 全局变量
      
      class Peoson {
      private:
      	std::string name;
          int age;
      
      public;
          void getYear() const {
          	// age = 1; 错误
          	year = getYear(); // 全局变量,可以修改
          	std::cout << year << endl;
      }
      };
      
      int main() {
          Person m;
          m.getYear();
          
          return 0;
      }
      
    • 例:

      1. const 限定符:

      const 用于声明一个常量对象,表示该对象的值不能被修改。例如:

      const int x = 5; // x 是一个常量整数,值不能改变
      // x = 10; // 这行会导致编译错误
      
      1. volatile 限定符:

      volatile 用于告诉编译器该对象可能会被程序以外的因素(如硬件)改变,因此不要对其进行优化。例如:

      volatile int sensor_value; // 这个值可能会被硬件设备随时更改
      
      1. 同时使用 const 和 volatile:
      const volatile int real_time_clock; // 值不能被程序修改,但可能会被硬件更新
      
      1. mutable 说明符:

      mutable 允许在 const 对象中修改特定成员。例如:

      class Example {
          mutable int cache_value;
      public:
          void update_cache() const {
              cache_value = 42; // 即使在 const 方法中也可以修改
          }
      };
      

      这些限定符主要用于:

      • 防止意外修改(const)
      • 处理可能被外部因素更改的数据(volatile)
      • 在需要时允许局部修改(mutable)
  2. &(左值)和&&(右值):表明该函数只能被左值或右值调用

    #include <iostream>
    
    class MyString {
    public:
        void Print() & {
            std::cout << "左值" << std::endl;
        }
        
        void Print() && {
            std::cout << "右值" << std::endl;
        }
    };
    
    int main() {
        MyString test;
        test.Print();     // 左值
        MySting().Print();// 右值
        
        return 0;
    }
    
  3. 显式调用成员函数(C++23新特性):

    • 左值:代表有明确地址和持久对象(在内存中存在且可以被引用),例如变量 dcd
    • 右值:代表临时对象或字面量,通常是没有持久地址的。例如 std::move(d) 会将 d 转换为一个右值引用(Derived&&)。
    class MyClass {
    public:
        void normalFunction(int x) {
            // 隐式调用
            value = x;
        }
        
        // 2。
        void explicitFunciton(this MyClass& self, int x) {
            // 显式调用
            self.value = x;
        }
        
        // 3.
        template<typename Self>
        void anyExplicitFunction(this Self& self, int x) {
            self.value = x;
        }
        
    private:
        int value;
    };
    
    MyClass test;
    test.normalFunction(1);
    test.explicitFunciton(1);
    test.anyExplicitFunction(1); // 这里是左值调用,所以self是&test且为非const
    // 效果是一样的
    
  • 当我们调用test.explicitFunciton(1);的时候,编译器把其转换成了类似于这样的代码MyClass::explicitFunciton(test, 1);

  • 第二种优势

    清晰性: 显式地看到 this 参数可以使代码意图更清晰。

    灵活性: 可以更灵活地控制 this 的类型,比如是否为 const, 是左值还是右值引用等。

    模板推导: 在模板中,可以推导出 this 的确切类型,这在继承情况下特别有用。

  • 第三种优势

    它能自动处理 const 和非 const 对象。

    它能处理左值和右值。

  • 例子

    class Base {
    public:
        template<typename Self>
        void print(this Self&& self) {  //直接写&&,会根据调用的参数来决定是左值还是右值
            std::cout << "I am " << self.getName() << std::endl;
        }
    
        virtual std::string getName() const { return "Base"; }
    };
    
    class Derived : public Base {
    public:
        std::string getName() const override { return "Derived"; }
    };
    
    int main() {
        Base b;
        Derived d;
        const Derived cd;
    
        b.print();   // 输出: I am Base
        d.print();   // 输出: I am Derived
        cd.print();  // 输出: I am Derived,注意这里调用的是 const 版本
    
        // 使用右值
        std::move(d).print();  // 也能正确工作,Self 被推导为 Derived&&
        // std::move(<对象名>) // 把对象从左值转换为右值
    }
    
  • 如果传的对象是const对象,只能调用const类型的成员函数,那么该函数会转换为const类型,反之非const,即为非const类型函数

参考链接
[ https://zh.cppreference.com/w/cpp/language/member_functions#const.E3.80.81volatile_.E5.8F.8A.E5.BC.95.E7.94.A8.E9.99.90.E5.AE.9A.E7.9A.84.E6.88.90.E5.91.98.E5.87.BD.E6.95.B0​  ]:

标签:const,右值,int,void,左值,C++,关键字,volatile,限定符
From: https://www.cnblogs.com/cha9/p/18378275

相关文章

  • c++贪心、模拟超详细讲解
    一、贪心算法基础1.1定义与原理定义:贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。原理:贪心算法通过局部最优选择来构造全局最优解。在每一步,算法都做出一个看起来最优的决策,期望通过局部最优达到全局......
  • c++SPFA细剖
    SPFA(ShortestPathFasterAlgorithm),作为一种高效的最短路算法,是Bellman-Ford算法的改进版本,结合了Dijkstra算法和Bellman-Ford算法的优点。下面我将从十个大的方面对SPFA算法进行详细剖析,每个大点下再分若干小点进行阐述。一、算法背景与起源1.1算法起源SPFA算法由西安交......
  • c++-类(中)
    c++-类(中)一、类的默认成员函数1.1什么是默认成员函数?1.2默认成员函数有哪些?二、构造函数2.1什么是构造函数?2.2构造函数的特点三、析构函数3.1什么是析构函数?3.2析构函数的特点四、拷贝构造函数4.1什么是拷贝构造函数?4.2拷贝构造函数的特点五、赋值运算符重载......
  • C++:强制类型转换速通
    强制类型转换核心为四个cast类型分别是:static_castdynamic_castconst_castreinterpret_cast补充:转换是否安全首先,派生类内一定有基类。基类指针可以指向派生类如果将指向基类的指针指向派生类,派生类对象在内存中的布局通常会以基类部分的开头,派生类可以看做是对基类......
  • C++:STL六大组件,知识点总结。
    STL知识点总结STL是C++标准库中的一个重要部分,提供了一组灵活通用的数据结构,核心是模板类。接下来是STL的主要组件及其功能简介。1.容器容器是用来存储和管理一组数据的对象。不同的容器适用于不同类型的数据存储需求。可理解为各种形式实现的存储结构顺序容器vec......
  • Qt/C++音视频开发81-采集本地麦克风/本地摄像头带麦克风/桌面采集和麦克风/本地设备和
    一、前言随着直播的兴起,采集本地摄像头和麦克风进行直播推流,也是一个刚需,最简单的做法是直接用ffmpeg命令行采集并推流,这种方式简单粗暴,但是不能实时预览画面,而且不方便加上一些特殊要求。之前就已经打通了音视频文件和视频流的采集,那是不是可以简单点的方式就能直接加入到原有的......
  • [底层原理] C/C++获取时间(将时间戳转换为年月日)?
    前言大家都知道,计算机中存储的时间是一个整数,在现在的编程语言中,可以很方便地将时间戳(整数)转换为字符串,但是如果没有这些我们该如何自己计算出呢?刚好以前研究过Nginx的源代码,我以他的代码为例,说明其背后的数学原理。当然在工程实践中,没有必要花时间自己实现转换的函数,所以本......
  • 【C++】类与对象篇三
    【C++】类与对象篇三一.运算符重载1运算符重载2赋值运算符重载3前置++和后置++重载4.const成员5.取地址及const取地址操作符重载一.运算符重载1运算符重载C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数函数名字为:关键字o......
  • 解决 C/C++ 程序执行一闪而过的方法
    作者:一去、二三里个人微信号:iwaleon微信公众号:高效程序员在VS编写控制台程序的时候,包括使用其他IDE(VisualC++)编写C/C++程序,经常会看到程序的执行结果一闪而过,要解决这个问题,可以在代码的最后加上system("pause")、getchar()、cin.get()。推荐方法比较常用的做......
  • C++11
    类型推导类型推导是C++的一种特性,允许编译器自动推导变量的类型,而不需要显式地制定类型。autoauto用于让编译器自动推导变量类型,常见用法:基本示例:autox=10;与容器一起使用:vector<string>names={"Alice","Bob"};for(autoit=names.begin();it!=names.en......