C++ 将引用用于类对象

发布时间:2023年12月30日

????????将类对象传递给函数时,C++通常的做法是使用引用。例如,可以通过使用引用,让函数将类 string、ostream、istream、ofstream和ifstream等类的对象作为参数。

????????下面来看一个例子,它使用了strng类,并演示了一些不同的设计方案,其中的一些是糟糕的。这个例子的基本思想是,创建一个函数,它将指定的字符串加入到另一个字符串的前面和后面。提供了三个这样的函数,然而其中的一个存在非常大的缺陷,可能导致程序崩溃甚至不同通过编译。

演示源码:

// Len_c.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <string>
using namespace std;

string version1(const string & s1, const string & s2);
const string & version2(string & s1, const string & s2);
const string & version3(string & s1, const string & s2);
int main()
{
	string input;
	string copy;
	string result;

	cout << "Enter a_string:";
	getline(cin, input);
	copy = input; 
	cout << "your string as entered: "<<input<< endl;	
	result = version1(input,"***");
	cout<< "Your string enhanced : "<< result << endl;
	cout << "Your origianl string:" << input << endl;

	result = version1(input, "###");
	cout << "Your string enhanced : " << result << endl;
	cout << "Your origianl string:" << input << endl;

	cout << "Resetting original string. \n";
	input = copy;
	result = version3(input, "@@@");
	cout << "Your string enhanced : " << result << endl;
	cout << "Your origianl string:" << input << endl;

	return 0;
}
string version1(const string & s1, const string & s2)
{
	string temp;
	temp = s2 + s1 + s2;
	return temp;
}
const string & version2(string & s1, const string & s2)
{
	s1 = s2 + s1 + s2;
	return s1;
}
const string & version3(string & s1, const string & s2)
{
	string temp;
	temp = s2 + s1 + s2;
	return temp;
}

执行结果:

此时,该程序已经崩溃。程序说明在程序的三个函数中,version1最简单;
?? ?string version1(const string & s1, const string & s2)
?? ?{
?? ??? ?string temp;
?? ??? ?temp = s2 + s1 + s2;
?? ??? ?return temp;
?? ?}

????????它接受两个string参数,并使用string类的相加功能来创建一个满足要求的新字符串。这两个函数参数都是const引用。如果使用string对象作为参数,最终结果将不变.
?? ?string version4(string sl,string s2) // 将达到同样的效果
?? ?
????????在这种情况下s1和s2将为string对象。使用引用的效率更高,因为函数不需要创建新的string对象,并将原来对象中的数据复制到新对象中。限定符 const 指出,该函数将使用原来的 string 对象,但不会修改它。

????????temp是一个新的string对象,只在函数versionl()中有效,该函数执行完毕后,它将不再存在。因此返回指向 temp的引用不可行,因此该函数的返回类型为 string,这意味emp 的内容将被复制到一个临时存储单元中,然后在 main()中,该存储单元的内容被复制到一名为result 的string中:

?? ?result = versionl(input,"***");

????????这种属性的结果是,如果形参类型为 const string &,在调用函数时,使用的实参可以是 string 对象或C-风格字符串,如用引号括起的字符串字面量、以空字符结尾的 char 数组或指向 char 的指针变量。因此,下面的代码是可行的:

?? ?result = versionl(input,"***");
?? ?
????????该函数可以修改s1,因为不同于s2,s1没有被声明为 const。
由于s1是指向 main()中一个对象 (input)的引用,因此将s1 作为引用返回是安全的。
由于s1 是指向input的引用,因此,下面一行代码:
?? ?
?? ?result = version2(input,"###");
?? ?
与下面的代码等价:
?? ?
?? ?version2(input,"###");// input altered directly by version2()
?? ?result = input; // reference to sl is reference to input
?? ?
然而,由于sI是指向 input 的引用,调用该函数将带来修改input 的副作用:
Your original string: It's not my fault.
Your string enhanced: ###It's not my fault.###
Your original string: ###It's not my fault,###

因此,如果要保留原来的字符串不变,这将是一种错误设计。
程序中的第三个函数版本指出了什么不能做:

?? ?const string & version3(string & sl,const string & s2) // bad design
?? ?{
?? ??? ?string temp;
?? ??? ?temp = s2 + s1 + s2;
?? ??? ?return temp;
?? ?}

????????它存在一个致命的缺陷:返回一个指向 version3()中声明的变量的引用。
这个函数能够通过编译(但编译器会发出警告),但当程序试图执行该函数时将崩溃。具体地说,问题是由下面的赋值语句引发的:result = version3(input,"@@@");
问题是由下面的赋值语句引发的:
?? ?????????result = version3(input,"@@@");
????????程序试图引用已经释放的内存。

文章来源:https://blog.csdn.net/wendyWJGU/article/details/135298751
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。