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

2015/01/10 13:57
阅读数 31


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

 

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;



 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部