每天学习一点c++之四——运算符重载

本文详细解析了C++中结构体的大小计算方法、char数组地址输出问题及引用的使用技巧。并通过实例介绍了四种类型转换运算符的用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<文章原创,转载请说明出处,联系信箱623730587@qq.com>

一、开题
        1 如果你一个人站在马路旁边看人来人往,突然有一个女孩子跑过来对你说”哇,这么冷得天,那个人穿短裤,好
           搞笑啊!“,这意味着什么?
        2 昨天理了个帅气的发型,去街上逛,于是就发生了上面一幕(得意一下),我想了老半天问“你是不是想泡我?”
           结果...
        3 好了,结果留给大家去想象,开始今天的内容。
二、c++中结构体或者类的大小(小小小知识点)
        1 有如下结构体
           struct Date
           {
                 int year;
                 int month;
                 int day;
                 void show()
                 {
                            cout << year << '-' << month << '-' << day << endl;
                 }
           }
          2 这个结构体的大小为12个字节,毫无疑问,但是我要提出一个问题,结构体的show()函数难道不占用空间大小
             吗?
          3 好吧,我不卖关子了,这是因为,变量是存放在栈或者堆里面的,而函数是存放在代码区里面的,表面上看,
             它们存放在同一个结构体中,但是本质上和c语言的结构体没什么区别,函数存放在代码区,变量存放在堆或
             栈里面,只是c++的设计者将它们的身体放在了一起而已,身在曹营心在汉啊!这就是传说中的、大名鼎鼎的
             封装,没有那么邪乎吧!
          4 现在大家明白了为什么上面的结构体大小为12了吧。
三、char数组地址的输出(小小小知识点)
        1 有如下的两个数组,其中第二个数组是存放在和data一样的栈空间中,而且地址相同,这是新的语法规定哦,
           表示将堆内存分配到栈内存中去,由于栈是自动回收的,这样就不用自己delete了,这个好吧?
            char data[100];
            int * pch = new (data)int[25];
        2 现在我们要输出data的地址
            cout << data << endl;
        3 上面的输出语句是一句乱码,为什么呢?数组名不是代表首地址吗?这是因为编译器会将char数组和char*理解
           为字符出串,哦,终于明白了,原来上面的输出语句输出的是一个字符串啊,没有赋值当然是乱码,那怎么办?
              cout << &data << endl;
           这样就行了。如果是int类型数组的话,编译器就不可能认为是字符串了。
四、引用
    1  引用就是变量的别名。就像我大名叫卓别林,小名叫狗蛋,其实是一个人。
    2  用法:
               1) 有如下变量
                        int a = 100;
                   上述语句执行意味着,操作系统要在内存中分配4个字节的区域,并给这块区域起名为a;一个区域有多个
                   名字是很正常的需求,所以就出现了引用的概念,到后面大家就会知道引用有大用了哦。
               2) 引用的定义
                        int& pa = a; 
                    这就表示给变量a取了一个别名pa。需要注意的是,定义引用的时候必须给引用赋值,下面语句不行。
                        int& pa;    // error
               3) 引用一旦初始化,那么被绑定的变量就服务终身。
                        int& pa  = a;
                        int& pa = b;    // error
                        ra = b; //right,这一句代码仅仅是将变量b的值赋值给ra。
               4)绝对不能返回局部变量的引用,因为一旦函数调用结束,局部变量本身就消失了,所以引用就是无效的。
                     可以返回全局变量的应用,静态变量的应用,堆内存变量的引用,和引用类型的引用。
      3 应用:
            1) 函数的传参
                   我们都知道,如果以值方式传参,那么传递的将是实参的一个副本,也就是将变量复制了一份传给函数。
                   假如我们要交换两个变量的值:
                        void swap(int x,int y);      // 值传递,要进行变量的复制,如果类型为struct类型,那么就会造成大规模
                                                                    的复制,另外变量的值不会发生交换
                        void swap(int* x,int* y);  // 指针的方式传递,变量的值发生交换,变量不会发生复制,但地址要复制,
                                                                    不管传递的是基本类型还是复合类型,都只复制4个字节的地址值。
                        void swap(int& x,int& y); // 如果以引用的方式传参,那么传递进函数的将会是变量本身,变量不复制

            2)函数的返回值
                   c语言中,函数的返回值一般作为右值,函数返回值一般是只读的,如果想让函数的返回值做左值,那么
                   就得用指针或者引用。
       4 常引用
           int& ra = 100; // error,因为引用只能和变量绑定,而不能和常量绑定。
           const int& ra = 100; // right
           c语言中,函数传递参数是加const的作用是,防止变量的值被修改
                   void fun(const int x);   // 防止值被修改
           而c++中,函数传递参数时,加const的作用有两个,防止变量的值被修改,和增强函数的兼容性。
                   void fun(const int& x);  //这样就既可以传递变量,也可以传递常量,增强了兼容性,也防止值被修改
        5 引用的底层实现
            1)const int* pa; / int const * pa;   
                 上述语句代表的是不能通过指针pa修改内存中的值。但是可以改变指针所指向的地址,这是c语言中的基
                 本的知识点。
                   int a = 20;
                   const int *pa = &a;
                   *pa = 30; // error,不能通过pa修改它所指向的内存中的值
                   int b = 40;
                   pa = &b;  // right,指针本身的地址可以改变

                  int *const pra = &a; // 注意,const的位置在*之后,和上面的语句对比就可以发现不同。这表明不能修改
                  指针的指向,也就是说pra指针和a的地址绑定,但是可以通过pra修改它所指向的内存中的值。
            2)引用则是变量的值可以改变,而变量的地址不可以改变(终生绑定的特性)。说到这里有没有发现,原来
                  引用的作用和const int* pa的作用是刚好相反的。其实引用本质就是上面的第二种写法int *const pra的定
                  义。
                   
       6 注意引用本身不占用内存大小。
       7 思考,引用和指针的联系和区别???
六、c++中的类型转换(四个转换运算符)
        1  首先说明c语言中的强制类型转换依然有效,但是c++中尽可能的避免这种强制类型转换。
        a  static_cast<要转换成的类型> (变量)   //在某一个方向上可以做隐式类型转换,那么在相反的转换方向上就可
                                                                           以使用static_cast
                       int *pi = new int(100);
                       void *pv = pi;   // 这个方向上,int* 可以隐式转换成void*
                       int *pt = pv;  // 报错,这个时候在另外一个方向上可以做static_cast<> ()的转换。
        b  dynamic_cast<类型>(变量) //用在具有多态性的父子类之间。(暂时不讲)
        c   const_cast<类型>(变量)  //专业的去常属性的
                  const int a = 100;
                  现在我我要改变a的值。
                  a = 200;   // 显然行不通
                  int *pa = &a; // 错误,a的地址具有常属性

                  int *pa = (int*)&pa;  // 强制转换,可以
                  *pa = 200;
                 cout << *pa << endl;  // 值是200
                 cout << a << endl;   // 值是100,这里很奇怪,因为c++编译器有优化技术,只要见到const类型的变量,会
                                                  像c语言中的宏一样进行快速替换,从而提高效率,但是上面的那种转换让人很迷惑
                 int* pa = const_cast<int*>(&a); // c++中专业的去常属性的操作符
        d   reinterpret_cast<类型>(变量)// 将指针变为整数,将整数转换为地址,即对内存进行重新解释,相当暴力。

        又一天结束了。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值