• c++ 关于引用变量你不知道的东西


    引用变量延迟绑定

    我们知道引用变量定义时要立刻赋值,告诉编译器他是谁的引用.如果不赋值,编译会失败.
    如果引用变量是单个定义的,对他赋值还比较简单.

    struct test_T
    {
    	int data;
    	//...其他成员
    	test_T(int _data = 0) :data(_data){}
    };
    
    struct SaveTest
    {
    	test_T & ref;
    	//...其他成员
    	SaveTest(test_T & _ref) :ref(_ref){}
    };
    
    int main(void)
    {
    	test_T *t   = new test_T[2];
    	SaveTest *s = new SaveTest[2]{t[0], t[1]};
    
    	for (int i = 0; i < 2; i++){
    		t[i].data = i + 1;
    	}
    
    	for (int i = 0; i < 2; i++){
    		printf("%d ", s[i].ref.data);
    	}
    	
    	return 0;
    }

    如果数组很大.就不方便了.不方便用{}一个一个赋值了.

    struct test_T
    {
    	int data;
    	//...其他成员
    	test_T(int _data = 0) :data(_data){}
    };
    
    struct SaveTest
    {
    	test_T & ref;
    	//...其他成员
    	SaveTest(test_T & _ref) :ref(_ref){}
    };
    
    int main(void)
    {
    	test_T *t   = new test_T[2000];
    	SaveTest *s = new SaveTest[2000];//没有用{},编译直接报错
    
    	for (int i = 0; i < 2000; i++){
    		t[i].data = i + 1;
    	}
    
    	for (int i = 0; i < 20; i++){
    		printf("%d ", s[i].ref.data);
    	}
    	
    	return 0;
    }

    我的想法是:先要骗过编译器,调用SaveTest构造函数的时候先赋个默认值,真正的我们用的对象
    引用,后面再慢慢赋值给它.

    struct test_T
    {
    	int data;
    	//...其他成员
    	test_T(int _data = 0) :data(_data){}
    };
    //******************************增加全局唯一默认值
    test_T default_test(-1);
    //******************************
    struct SaveTest
    {
    	test_T & ref;
    	//...其他成员               修改构造函数
    	SaveTest(test_T & _ref = default_test) :ref(_ref){}
    };
    
    int main(void)
    {
    	test_T *t   = new test_T[2000];
    	SaveTest *s = new SaveTest[2000];//编译ok
    
    	for (int i = 0; i < 10; i++){
    		t[i].data = i + 1;
    		s[i].ref = t[i];//重新赋值
    	}
    
    	for (int i = 0; i < 10; i++){
    		printf("%d ", s[i].ref.data);
    	}
    	
    	return 0;
    }

    输出:

    怎么会这样???.(我现在还是不理解)
    通过上面的方式,可以做到延迟赋值,但是赋值很奇怪,单个可以被修改,但是所有成员的ref都会一
    起被更改,真是秀儿~.
    行,那就只能换个思路了.引用不能延迟赋值,指针类型可以吧,我用指针类型.

    struct test_T
    {
    	int data;
    	//...其他成员
    	test_T(int _data = 0) :data(_data){}
    };
    //******************************全局唯一默认值
    test_T default_test(-1);
    //******************************
    struct SaveTest
    {
    	test_T * ref;
    	//...其他成员
    	SaveTest(test_T * _ref = nullptr) :ref(_ref){}
    };
    
    int main(void)
    {
    	test_T *t   = new test_T[2000];
    	SaveTest *s = new SaveTest[2000];//编译ok
    
    	for (int i = 0; i < 10; i++){
    		t[i].data = i + 1;
    		s[i].ref = &t[i];//重新赋值
    	}
    
    	for (int i = 0; i < 10; i++){
    		printf("%d ", s[i].ref->data);
    	}
    	
    	return 0;
    }

    哼~,可以了吧.

    等一下,等一下,跑题了,虽然这样做可以,但是不是用的引用实现的啊.
    练剑的最高境界就是无剑胜有剑,达到人剑合一,剑既是我,我既是剑.
    是时候,让指针跟引用合二为一啦.

    struct test_T
    {
    	int data;
    	//...其他成员
    	test_T(int _data = 0) :data(_data){}
    };
    
    union MyUnion
    {
    	test_T * ptr;
    	test_T & ref;
    	MyUnion(){}
    };
    struct SaveTest
    {
    	MyUnion u;
    	//...其他成员
    	SaveTest(test_T& _ref){
    		u.ptr = &_ref;
    	}
    	
    	void set(test_T& _ref){
    		u.ptr = &_ref;
    	}
    	test_T& get(){
    		return u.ref;
    	}
    };
    
    int main(void)
    {
    	test_T *t   = new test_T[2000];
    	SaveTest *s = new SaveTest[2000];//编译ok
    
    	for (int i = 0; i < 10; i++){
    		t[i].data = i + 1;
    		s[i].set(t[i]);//重新赋值
    	}
    
    	for (int i = 0; i < 10; i++){
    		printf("%d ", s[i].get().data);
    	}
    	
    	return 0;
    }

    使用者角度:
    SaveTest *s = new SaveTest[2000];//只是定义变量,没有绑定
    s[i].set(t[i]);//第一次具体赋值,绑定引用(站在使用者角度看)
    s[i].get();//得到一个引用
    内部:
    每次保存的都是指针,每次使用的时候用引用.

    从汇编角度,引用和指针,本是一家.
    还有,上面那个问题,有兴趣的可以试一下,交流交流.


    __EOF__

  • 本文作者: YourName
  • 本文链接: https://www.cnblogs.com/jlh-/p/16868604.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    Windows通过RDP异地远程桌面Ubuntu【内网穿透】
    基于二维切片图序列的三维立体建模MATLAB仿真
    jwbasta-Springboot集成Quartz
    C#运算符执行顺序对照表
    【GUI】-- 10 贪吃蛇小游戏之静态面板绘制
    HCIA-HarmonyOS设备开发V2.0证书
    怎么修复老照片?给你推荐这几个修复方法
    华为畅享系列多款产品升级HramonyOS 4.2版本,一篇带你解读
    图片一键调整工具V1.0-免费版
    Pip版本问题导致Python模块安装失败
  • 原文地址:https://www.cnblogs.com/jlh-/p/16868604.html