c++的引用(二)
/*按地址传递*/
#include <iostream>
using namespace std;
void swap(int *a, int *b)
{
int c;
c = *a;
*a = *b;
*b = c;
}
int main()
{
int a = , b = ;
cout << "交换前" << "a: " << a << " b: " << b << endl;
swap(&a, &b); // 按地址传递
cout << "交换后" << "a: " << a << " b: " << b << endl;
return ;
}
按别名传递
/*按别名传递*/
/*我们可以将a和b的别名传递到swap函数中,将swap函数的接收参数改为接收两个别名,调用时候将a和b传递进去即可,
这样参数a和b就变成了主函数中的a和b的别名,由于别名即自身,所以对别名的操作即是对main函数的a和b的操作,
或者说参数a和b即main函数中的a和b*/
#include <iostream>
using namespace std;
void swap(int &a, int &b)
{
int c;
c = a;
a = b;
b = c;
}
int main()
{
int a = , b = ;
cout << "交换前" << "a: " << a << " b: " << b << endl;
swap(a, b);
cout << "交换后" << "a: " << a << " b: " << b << endl;
return ;
}
按值传递比较消耗系统资源,下面来演示
/*按值传递对象*/
#include <iostream>
using namespace std;
class A
{
public:
A() {cout << "执行构造函数创造一个对象\n";}
A(A&) {cout << "执行复制函数创建该对象的副本\n";}
~A() {cout << "执行析构函数删除该对象\n";}
};
A fun(A one)
{
return one;
}
int main()
{
A a;
fun(a);
return ;
}
上面代码如果改成按地址传递就会少调用一次复制构造函数,当然跟着也会少调用一次析构函数,当然如果仍然返回一个值的话,
仍然会调用一次复制构造函数来创建一个返回值,仍然浪费了系统资源,
#include <iostream>
using namespace std;
class A
{
public:
A() {cout << "执行构造函数创造一个对象\n";}
A(A&) {cout << "执行复制函数创建该对象的副本\n";}
~A() {cout << "执行析构函数删除该对象\n";}
};
A fun(A *one)
{
return *one;
}
int main()
{
A a;
fun(&a);
return ;
}
当然如果仅仅返回一个地址的话,就会省去上面的因要返回一个值而调用复制构造函数和析构函数的过程
/*按值传递对象*/
#include <iostream>
using namespace std;
class A
{
public:
A() {cout << "执行构造函数创造一个对象\n";}
A(A&) {cout << "执行复制函数创建该对象的副本\n";}
~A() {cout << "执行析构函数删除该对象\n";}
};
A *fun(A *one)
{
return one;
}
int main()
{
A a;
fun(&a);
return ;
}
按值传递虽然可以避免重复调用复制构造函数和析构函数 ,但是由于它得到了该对象的内存地址,可以随时修改该对象的数据。所以它实际上是破坏了按值传递的保护机制,不过我们仍然有解决办法,那就是用const指针来接收对象,这样就可以防止任何试图对该对象进行操作的行为,并且保证返回一个不可被修改的对象
这样的话我们无法通过返回的地址来修改对象的值,但是我们仍然可以通过该对象的名字来修改该对象。因为指向常量的长指针只是限制我们用该指针修改它指向的对象的值,但是它并不会改变原始对象的属性,不修改该对象的值的操作可以利用传递回来的地址进行,
注意:子函数返回的指向常量的长指针的值 必须用指向常量的长指针来接收;否则会报错!!!!!!!!!!!!!!!!!!!!!!!!
/*注意不要用对象来接收返回的别名,由于别名并不是对象,只是原来对象的另一个名字,所以呢执行复制构造函数以后,并没有*/
#include <iostream>
using namespace std;
class A
{
public:
A() {cout << "执行构造函数创造一个对象\n";}
A(A&) {cout << "执行复制函数创建该对象的副本\n";}
~A() {cout << "执行析构函数删除该对象\n";}
int get()const{return x;}
void set(int i) {x = i;}
private:
int x;
};
const A *const fun(const A *const one) //保证传进来的数据不被修改,返回的值也不被修改
{
one->get();
return one;
}
int main()
{
A a;
const A *const p = fun(&a);
a.set();
cout << "p:" << p << endl;
cout << "a:" << &a << endl;
return ;
}
下面是引用的代码,注意当子函数返回一个引用的时候不能用一个对象来接收该引用,这个对象是不会得到一个对象的数据的,因为返回的仅仅是一个引用的名字而已,而要定义一个引用来接收返回的引用,如果返回一个对象的时候倒是可以定义一个对象来接收
/*注意不要用对象来接收返回的别名,由于别名并不是对象,只是原来对象的另一个名字,
即返回的不是对象,而是对象的另一个名字,所以不能用对象来接收一个别名,而要用一个别名来接收它
如果返回的是一个对象的话就可以用一个对象来接收它,这样执行复制构造函数的时候也会复制返回的对象的数据
所以执行复制构造函数之后并没有复制该对象的数据*/ /*别名常量不能修改它所引用的对象的数据const A &b = a; 即定义一个类A中a对象的别名常量b,*/
#include <iostream>
using namespace std;
class A
{
public:
A() {cout << "执行构造函数创造一个对象\n";}
A(A&) {cout << "执行复制函数创建该对象的副本\n";}
~A() {cout << "执行析构函数删除该对象\n";}
int get()const{return x;}
void set(int i) {x = i;}
private:
int x;
};
A& fun(A &one)
{
one.get();
return one;
}
int main()
{
A a;
A &b = fun(a);
a.set();
cout <<b.get()<< endl;
return ;
}
引用本来就是常量,我们不能改变它所引用的对象,而且当我们不想让该引用修改它所引用的对象的值的时候,我们可以把它定义为别名常量,
这个时候用该引用修改原对象的名字就是非法的,会报错,只能用原对象的名字来修改这个对象
/*别名常量不能修改它所引用的对象的数据const A &b = a; 即定义一个类A中a对象的别名常量b,这时候不能用b修改a的数据*/
#include <iostream>
using namespace std;
class A
{
public:
A() {cout << "执行构造函数创造一个对象\n";}
A(A&) {cout << "执行复制函数创建该对象的副本\n";}
~A() {cout << "执行析构函数删除该对象\n";}
int get()const{return x;}
void set(int i) {x = i;}
private:
int x;
};
const A& fun(const A &one) //保证返回的值不被修改,传进来的对象也不被修改
{
one.get();
return one;
}
int main()
{
A a;
const A &b = fun(a);
a.set();
cout <<b.get()<< endl;
return ;
}
c++的引用(二)的更多相关文章
- Unity Inspector 给组件自动关联引用(二)
通过声明的变量名称,主动关联引用. 使用这个关联引用两种方式1. 给你组件继承 MonoAutoQuote 点击组件inspector 按钮执行2. 给你组件类添加[AAutoQuote] 特性 ...
- JDK1.8新特性之(二)--方法引用
在上一篇文章中我们介绍了JDK1.8的新特性有以下几项. 1.Lambda表达式 2.方法引用 3.函数式接口 4.默认方法 5.Stream 6.Optional类 7.Nashorm javasc ...
- C语言教学--二维数组和指针的理解
对于初学者对二维数组和指针的理解很模糊, 或者感觉很难理解, 其实我们和生活联系起来, 这一切都会变得清晰透彻. 我们用理解一维数组的思想来理解二维数组, 对于一维数组,每个箱子里存放的是具体的苹果, ...
- 【学习笔记】【C语言】二维数组
1. 什么是二维数组 一个数组能表示一个班人的年龄,如果想表示很多班呢? 什么是二维数组?int ages[3][10]; 三个班,每个班10个人 相当于3行10列 相当于装着3个一维数组 二维数组是 ...
- jenkins-APP打包页面展示二维码
背景: 客户要求在APP打包页面展示二维码.虽然感觉这个功能很鸡肋,但是还是加上吧. 效果展示: 配置: 在上图中,106对应的内容是BuildName,我们可以通过build-name-setter ...
- 【Java学习笔记之八】java二维数组及其多维数组的内存应用拓展延伸
多维数组声明 数据类型[][] 数组名称; 数据类型[] 数组名称[]; 数据类型数组名称[][]; 以上三种语法在声明二维数组时的功能是等价的.同理,声明三维数组时需要三对中括号,中括号的位置可以在 ...
- java_方法引用
什么是方法引用? 个人简述方法引用: 方法引用主要是针对已经有的方法来让目前的编程更加简洁 当我们想要使用一个接口的子类的时候,子类需要重写这个接口中的抽象方法, 被重写的这个方法参数列表固定,返回值 ...
- Block 循环引用(上)
iOS的内存管理机制 Objective-C在iOS中不支持GC(垃圾回收)机制,而是采用的引用计数的方式管理内存. 引用计数:在引用计数中,每一个对象负责维护对象所有引用的计数值.当一个新的引用指向 ...
- VS2015+OpenGL4.0开发编译时弹出错误:glaux.lib(tk.obj) : error LNK2019: 无法解析的外部符号 _sscanf,该符号在函数 _GetRegistrySysColors@8 中被引用
一.问题描述: VS2015+OpenGL4.0开发编译时弹出如下所示的错误: 1>glaux.lib(tk.obj) : error LNK2019: 无法解析的外部符号 _sscanf,该符 ...
- 《C语言程序设计》指针篇<二>
通过指针引用多维数组 如何理解二维数组元素的地址? 要知道,这本书用了整整两页的内容来讲解这方面的知识,从这里足以看出来理解通过指针来引用二维数组是一件比较麻烦的事情,但是我认为理解并不难. 什么是二 ...
随机推荐
- Java虚拟机体系结构
转自:http://www.cnblogs.com/java-my-life/archive/2012/08/01/2615221.html JAVA虚拟机的生命周期 一个运行时的Java虚拟机实例的 ...
- PHP练习项目笔记之COOKIES
主要是在登录和退出的时候,设置cookies.来保存登录和安全退出 1:在登录页面设置 //设置cookies的值 _setcookies($_rows['tg_username'], $_rows[ ...
- Latex调整行距
修改行间距的方法: \usepackage{setspace}%使用间距宏包 \begin{document} \begin{spacing}{2.0}%%行间距变为double-space 双倍行距 ...
- 闲来无事写写-Huffman树的生成过程
前言:最近项目上一直没事干,感觉无聊到了极点,给自己找点事做,补一下大学没有完成的事情,写一个huffman算法Java版的,学校里面写过c语言的. 因为很久没搞数据结构和算法这方面了(现在搞Java ...
- 不用注册热键方式在Delphi中实现定义快捷键(又简单又巧妙,但要当前窗体处在激活状态)
第一步:在要实现快捷键的窗体中更改属性“KeyPreview”为True:第二步:在要实现快捷键的窗体中的OnKeyPress事件中填入一个过程名称(在Object Inspector中),填写好后回 ...
- 共享内存操作类(C#源码)
原文 http://blog.csdn.net/yefanqiu/article/details/1717458 VC++的共享内存操作代码实现起来相对比较容易,但是用C#语言来实现,就有一定难度,由 ...
- 宣布正式发布 Windows Azure 多重身份验证
身份和访问管理是安全之锚,是企业 IT 部门的首要任务.它是随时随地向员工.合作伙伴和客户提供访问的关键所在.今天,我们非常高兴地宣布正式发布 Windows Azure 多重身份验证,从而为 IT ...
- How many prime numbers(求素数个数)
How many prime numbers Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- 关于SpringMVC中找不到<mvc:resources/>标签的解决办法
在springMVC中我们经常会用到<mvc:resources/>标签,但是有些编辑器中的schema过于陈旧.导致找不到<mvc:resources/>标签. 经过试验,有 ...
- 2014多校3 Wow! Such Sequence!段树
主题链接:http://acm.hdu.edu.cn/showproblem.php? pid=4893 这个问题还真是纠结啊--好久不写线段树的题了.由于这几天学伸展树.然后认为线段树小case了. ...