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语言程序设计》指针篇<二>
通过指针引用多维数组 如何理解二维数组元素的地址? 要知道,这本书用了整整两页的内容来讲解这方面的知识,从这里足以看出来理解通过指针来引用二维数组是一件比较麻烦的事情,但是我认为理解并不难. 什么是二 ...
随机推荐
- PHP-购物网站开发设计(一)
2015-07-6 开始使用PHP完成简单购物网站的设计,首先要选择合适的软件平台,所以今天先记录平台的选择与搭建: 我选择使用Apache24 + PHP 5.6 + MySQL 开发环境完成PHP ...
- BZOJ 4010: [HNOI2015]菜肴制作( 贪心 )
把图反向,然后按拓扑序贪心地从大到小选, 最后输出.set比priority_queue慢... --------------------------------------------------- ...
- django1.4.5无法安装MySQLdb1.2.3
解决办法是: yum install python-devel mysql-devel zlib-devel openssl-devel 然后再build.install
- 【转】DevExpress控件安装
原文链接: DevExpress控件安装.汉化使用教程 - 田园里的蟋蟀 学习网址: 1.DevExpress控件中文网 2.DevExpress控件中文网使用教程 3.DevExpress控件使用经 ...
- GE_OG_CALC_COLUMN_EMPTY
CREATE OR REPLACE PROCEDURE CUST_MKT_DWH.GE_OG_CALC_COLUMN_EMPTY(P_TABLE_NAME IN VARCHAR2) IS --TYPE ...
- MVC-04 视图(1)
不可否认的,View应该是整个ASP.NET MVC项目开发过程中最花时间的部分,因为与显示逻辑相关的技术五花八门,你可能要学习的有HTML.CSS.JavaScript.DOM.JQuery.JSO ...
- Hbuilder 常用快捷键汇总
朋友推荐用Hbuilder编辑器,看了下Hbuilder官网和那视频,感觉牛逼哄哄的, 自己也就体验了一下,打开Hbuilder的快捷键列表,每个快捷键都体验了一下,以下展示出来的,每一个都是精华,每 ...
- VC编程中如何设置对话框的背景颜色和静态文本颜色
晚上编一个小程序,涉及到如何设置对话框的背景颜色和静态文本颜色.这在VC6.0中本来是一句话就搞定的事.在应用程序类中的InitInstance()函数添加: //设置对话框背景和文本颜色 SetDi ...
- CF 191 div2
A.数据量很小,直接爆搞. #include <iostream> #include <cstdio> #include <algorithm> #include ...
- Informatica 9.5.1 安装配置
Informatica 结构 1个或多个资源库(Respository) PowerCenter数据整合引擎是基于元数据驱动的,提供了基于数据驱动的元数据知识库(Repository),该元数据知识 ...