文档章节

指针的引用——在函数中的巧妙应用

自由的角马
 自由的角马
发布于 2015/01/10 13:57
字数 937
阅读 8
收藏 0


前面有一篇文章讲了指针与引用。并且还提到不能定义指向引用的指针(因为引用不是对象,没有实际的地址)。那么,能否定义指针的引用呢?答案是肯定的,因为指针本身就是一个对象。即然是对象,就能定义一个引用邦定该对象。先来看看指针的引用的用法:

 

int类型为例如下:

void ReferencePointer()
{
	int		i = 5;		// 变量i
	int*	p = &i;		// 指针p,指向变量i
	int*&	pr = p;		// 指针的引用,与p指向同一个变量i
	cout << i << "  " << *p << "  " << *pr << endl;
	i = 10;
	cout << i << "  " << *p << "  " << *pr << endl;

	cout << "addr: " << p << "  " << pr << endl;	// 指针的引用其它就是指针p的一个别名,和p有相同的地址
	pr = NULL;										// 因此也可以给指针赋空
	cout << "addr: " << p << "  " << pr << endl;
}

结果:

5  5  5

10  10  10

addr: 0045FE50  0045FE50

addr: 00000000  00000000

 

在函数中,指针的引用作为参数可以起到很巧妙的作用。

 

假设有一个书的类Book,基定义如下:

struct Book

{

    string isbn;

    string name;

    double price;

    string author;

};


现在需要这样一个函数:有一个文件存放着一本书的相关信息(ISBN、书名、价格),现要从这个文件中读取信息并赋给Book的对象。

 

要定义这样一个函数,我们首先会想到的是有一个输入(文件的路径)和一个输出(Book的对象)。你可能会这样定义函数:

Book* GetBookFromFile(const string& filePath);

这种方式你必须在函数体内创建Book的对象(也就创建一个Book的内存空间),但函数体内创建的内存空间只在函数的作用域内有效,在函数体外是无效的,也就是说返回的指针将指向一个任意的值,这将是非常危险的。

 

如函数内:

 


在函数被调用后:

 

 

 

 

 

既然不行,您应该会想到另外一种定义方式如下:

Book GetBookFromFile(const string& filePath);

没错,这样定义确实可以,但需要在函数体内声明一个Book的对象,函数返回值的时候会进行一次对象的拷贝。这样增加了一个对象拷贝的过程,使效率降低。

Book GetBookFromFile(const string& filePath)
{
	Book book;
	fstream fileInput(filePath);
	fileInput >> book.isbn >> book.name >> book.price;
	return book;
}

 

 

 

 

 

您可能还会想到这种方式:

void GetBookFromFile(Book &book, const string& filePath);

没错,这确实可以解决上面的问题,不用再对对象进行拷贝。但新的问题又来了,上层调用这个函数时,如果要判断返回book对象是否正确获取了文件的信息得逐个地判断基属性是否空,如下代码。这无疑加重了上层调用的负担。

Book book;

GetBookFromFile(book, "E:\\book.txt");

if (!book.isbn.empty() && !book.name.empty() && book.price > 0)

{

    // TO DO ...

}

当然,这有一种改进的方式,就是把返回值类型void改为bool,这样就可以通过返回的bool值确定函数是否成功调用。

 

 

 

针对上面的这个问题,如果返回的是Book的指针,直接判断返回的指针是否为NULL就可以。那么您可以有以下两种定义:

void GetBookFromFile(Book* book, const string& filePath);

void GetBookFromFile(Book*& book, const string& filePath);

当然,我是建议选择第二种方式,因为引用确保了传进来的指针有一个正确的值(引用必须在定义时被初始化)

 

定义如下:

 

void GetBookFromFile(Book* pBook, const string& filePath)
{
	if (pBook == NULL)
	{
		return;
	}
	fstream fileInput(filePath);
	fileInput >> pBook->isbn >> pBook->name >> pBook->price;
}

void GetBookFromFile(Book*& pBook, const string& filePath)
{
	if (pBook == NULL)
	{
		return;
	}
	fstream fileInput(filePath);
	fileInput >> pBook->isbn >> pBook->name >> pBook->price;
}

 

对这两个函数,调用方式都可以如下:

Book* pBook = new Book();
	pBook->author = "SimileSunrise";
	GetBookFromFile(pBook, "E:\\book.txt");
	delete pBook;



 

本文转载自:http://blog.csdn.net/luoweifu/article/details/39119487

自由的角马
粉丝 1
博文 269
码字总数 0
作品 0
文山
私信 提问
block本质探寻五之atuto类型局部实例对象

说明:阅读本文章,请参考之前的block文章加以理解; 一、栈区block分析 //代码 //ARCvoid test1(){ } //打印 2019-01-14 17:24:12.118653+0800 MJ_TEST[6638:285938] Person dealloc2019-01...

春天里的花骨朵
01/15
0
0
C++基础常识快速掌握--自学笔记(一)

这里是C++自学时自己做的笔记,记住C++特有的特性,通用性的不做记录,主要以代码实例加深对定义的枯燥的理解吗,所以重点注意代码中的注释内容,快速了解基础内容,了解代码; C++常见特殊:...

bbs11007
2017/11/24
0
0
NDK开发中这些基本知识你都懂吗

JNIEnv 定义: 相当于一个jni上下文对象。 作用: 通过JNIEnv的指针能够对Java端的代码进行操作: a.创建Java对象. jstring str = (env).NewStringUTF("终端研发部"); jclass jclazz = (env)...

codeGoogle
2017/09/21
0
0
block本质探寻一之内存结构

一、代码——命令行模式 //main.m #import struct block_impl { }; struct mainblockdesc_0 { }; struct mainblockimpl_0 { }; int main(int argc, const char * argv[]) { // ^{// NSLog(@"......

春天里的花骨朵
01/09
0
0
C++ 备忘录 ( 持续更新中... )

Tip 1: #include包含头文件的问题 新的编译器格式: #include <iostream>using namespace std; 旧的编译器格式: #include <iostream.h> 注:旧的编译器格式中,包含头文件后,不添加 “usi...

谷鹏
2011/04/12
417
1

没有更多内容

加载失败,请刷新页面

加载更多

golang-字符串-地址分析

demo package mainimport "fmt"func main() {str := "map.baidu.com"fmt.Println(&str, str)str = str[0:5]fmt.Println(&str, str)str = "abc"fmt.Println(&s......

李琼涛
今天
4
0
Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
今天
6
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
今天
8
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
今天
5
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部