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语言程序设计》指针篇<二>
通过指针引用多维数组 如何理解二维数组元素的地址? 要知道,这本书用了整整两页的内容来讲解这方面的知识,从这里足以看出来理解通过指针来引用二维数组是一件比较麻烦的事情,但是我认为理解并不难. 什么是二 ...
随机推荐
- vs2013出现ISO C++ conformant解决办法
出现:错误 1 error C4996: 'strnset': The POSIX name for this item is deprecated. Instead, use the I ...
- 关于CDH5.2+ 添加hive自定义UDAF函数的方法
- UIWebView的三种加载方式
一.使用UIWebView 将web content 嵌入到应用上. API提供了三种方法: - (void)loadRequest:(NSURLRequest *)request; - (void) ...
- C#计算时间差。
C#中怎么计算两时间相差多少.计算2个时间之间的差,可以计算到时分秒! <1>label1.Text = “2004-1-1 15:36:05″;label2.Text = “2004-3 ...
- 在SQL2005中部署CLR 程序集
原文 在SQL2005中部署CLR 程序集 有关于CLR函数的用途和用法,请了解 SQL Server CLR 极速入门,启用.设计.部署.运行 http://www.yongfa365.com/It ...
- php订单生成唯一Id
一般用到一个函数: uniqid(prefix,more_entropy) 参数 描述 prefix 可选.为 ID 规定前缀.如果两个脚本恰好在相同的微秒生成 ID,该参数很有用. more_ent ...
- BZOJ 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚
题目 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚 Time Limit: 5 Sec Memory Limit: 64 MB Description Farm ...
- 九款让WordPress成为赚钱利器的广告插件
Blog有了很不错的流量后,看到别人博客挂的广告挣$,是否也有挂广告的冲动,但是,修改wordpress模版去让人不厌其烦,布局.样式都的重新修改一下,为了不那么麻烦,笔者整理的几款wordpress ...
- Thread.Sleep(0)的意义 操作系统中CPU的竞争策略
在线程的学习中遇到的 不太明白就搜了一下 有一篇觉得写得很好的分享一下 转载:http://www.360doc.com/content/12/1220/07/1054746_255212714.s ...
- iOS内存管理 ARC与MRC
想驾驭一门语言,首先要掌握它的内存管理特性.iOS开发经历了MRC到ARC的过程,下面就记录一下本人对iOS内存管理方面的一些理解. 说到iOS开发,肯定离不开objective-c语言(以下简称OC ...