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();//得到一个引用
内部:
每次保存的都是指针,每次使用的时候用引用.
从汇编角度,引用和指针,本是一家.
还有,上面那个问题,有兴趣的可以试一下,交流交流.
c++ 关于引用变量你不知道的东西的更多相关文章
- C++引用变量学习
版权所有,转载请注明来源 (1)reference variable(rv) 主要用处是作为方程的形式参数,使用rv 可以直接对原数据进行操作而不是该数据的拷贝,节省了时间和空间,尤其是对于结构体以及 ...
- Java基础-被final修饰的引用变量的指向
final修饰的引用变量一旦初始化赋值之后就不能再指向其他的对象,那么该引用变量指向的对象的内容可变吗?看下面这个例子: public class Test { public static void ...
- PHP GC垃圾回收机制之引用变量回收周期疑问
普通的引用变量的销毁大家都知道, 当unset的时候如果refcount = 0 则认为无用, 销毁. 但是手册中提到一点会有递归引用的问题,很是奇葩 代码如下 <?php $a = 1; $a ...
- C++引用变量(转)
引用变量 c++中引用变量的使用: 定义: int rate=80; int & pt=rate 1.pt 是引用变量,申明引用变量时必须将其初始化.pt 和rate 的值指向相同的内存变量 ...
- c#问答篇:对象与引用变量-----初学者的困惑
转自:http://www.cnblogs.com/huangyu/archive/2004/08/02/29622.html 从宏观的角度来看,对象是类的实例.比如: //定义一个名为Someone ...
- C++ primer(八)--内联函数 引用变量 引用传递函数参数 函数重载/模板/模板具体化
一.内联函数 常规函数和内联函数的区别在于C++编译器如何将他们组合到程序中.编译过程的最终产品是可执行程序--由一组机器语言指令组成.运行程序时,操作系统将这些指令载入到计算机内存中,因此每 ...
- C++学习笔记29,引用变量(1)
引用变量在创建的时候就必须初始化.无法创建一个未被初始化的引用. #include <iostream> using namespace std; int main() { int x=1 ...
- [DB][mybatis]MyBatis mapper文件引用变量#{}与${}差异
MyBatis mapper文件引用变量#{}与${}差异 默认,使用#{}语法,MyBatis会产生PreparedStatement中.而且安全的设置PreparedStatement參数,这个过 ...
- PHP关于foreach使用引用变量的坑
写PHP好多年,但仍然会犯低级错误,今天遇到个 foreach中引用变量时的坑,PHP版本为 5.6.12 代码如下: <?php $arr = ['a', 'b', 'c', 'd', 'e' ...
随机推荐
- 解决git报错
解决git报错:fatal: unable to access "https://github.com/.../.git/" 1.在git中执行(记得分开执行) git confi ...
- 算法模板:dijkstra
#include<iostream> #include<algorithm> #include<cstring> #include<string> #i ...
- Knative部署应用以及应用的更新、应用的分流(二)
1. 应用的更新 1.1 更新hello-example应用 1.更新应用的环境变量 可通过命令行的方式亦可以通过读取配置文件的方式,这里主要来看命令行的方式 [root@kn-server-mast ...
- API设计中性能提升的10种解决方法
api的设计涉及到的方面很多, 分类是一个基本的思考方式.如果可以形成一个系列性的文字,那就从性能开始吧. 就像任何性能一样,API 性能主要取决于如何响应不同类型的请求.例如:典型的电商场景,显示用 ...
- 【Vue学习笔记】—— vuex的语法 { }
学习笔记 作者:o_Ming vuex Vuex ++ state ++ (用于存储全局数据) 组件访问 state 中的全局数据的方式1: this.$store.state.全局数据 组件访问 s ...
- Erda 开源的迷失和反思
前言 Erda 是我从2018年初加入上家公司直到今年初离开的四年时间里一直在做的一个云原生 PaaS 平台.在开源之前,Erda 在公司内部的名字代号是 D ,在21年初改名为现在的 Erda 进行 ...
- vscode调试thinkhphp
第一步先安装xdebug扩展,我用宝塔环境,所以一键安装 第二步.在vscode中安装插件 我的php.ini是这样的 xdebug.remote_enable = 1 xdebug.remote_a ...
- MySQL集群搭建(1)-主备搭建
数据库在任何业务中都是最重要的环节之一,这就对数据库架构提出的较高的要求.单点数据库永远不应该出现在生产环境,我们已经目睹过太多由于单点.备份缺失造成的损失,所以,搭建高可用 MySQL 集群是非常有 ...
- Query String Query和Sumple Query String
- Bootstrap5 如何创建多媒体对象
一.在Bootstra5中使用媒体对象 Bootstrap 媒体对象在版本 5 中已经停止支持了.但是,我们仍然可以使用 flex 和 margin 创建包含左对齐或右对齐媒体对象(如图像或视频)以及 ...