C++ 将引用用于类对象

        将类对象传递给函数时,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,"@@@");
        程序试图引用已经释放的内存。

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WendyWJGu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值