高效率的C++函数返回值
来源:互联网 发布:bing软件 编辑:程序博客网 时间:2024/05/11 12:52
1.有时候返回引用可以提高效率,有些情况不能返回引用
类的赋值运算符函数中,返回对象的引用可以显著提高效率。
- class String
- {
- public:
- String & operate=(const String &other);
- // 相加函数,如果没有friend修饰则只许有一个右侧参数
- friend String operate+(const String &s1, const String &s2);
- private:
- char *m_data;
- }
- String & String::operate=(const String &other)
- {
- if (this == &other)
- return *this;
- delete m_data;
- m_data = new char[strlen(other.data)+1];
- strcpy(m_data, other.data);
- return *this; // 返回的是 *this的引用,无需拷贝过程
- }
上面如果用“值传递”的方式,虽然功能仍然正确,但由于return语句要把 *this拷贝到保存返回值的外部存储单元之中,增加了不必要的开销,降低了赋值函数的效率。
String的相加函数operate + 的实现如下:
- String operate+(const String &s1, const String &s2)
- {
- String temp;
- delete temp.data; // temp.data是仅含‘/0’的字符串
- temp.data = new char[strlen(s1.data) + strlen(s2.data) +1];
- strcpy(temp.data, s1.data);
- strcat(temp.data, s2.data);
- return temp;
- }
对于相加函数,应当用“值传递”的方式返回String对象。如果改用“引用传递”,那么函数返回值是一个指向局部对象temp的“引用”。由于temp在函数结束时被自动销毁,将导致返回的“引用”无效。
设想一下,相加运算符重载函数应该是参数列表中的两个对象相加,必须产生一个新的对象并返回它。这区别于+=运算符,+=运算符是将右边的对象累加到左边的对象上,因此+=的实现应当返回运算符左边对象的引用。
2. 返回静态局部变量的引用往往会带来问题
上面已经说了operator+函数中不能返回临时对象的引用,那么返回静态局部变量的引用呢?静态局部变量的生命不会随着函数消失而结束,返回其引用似乎可行,但这样做往往会给程序带来问题。
- const Rational& operator*(const Rational& lhs, const Rational& rhs)
- {
- static Rational result; // static object to which a reference will be returned
- result = ... ; // multiply lhs by rhs and put the product inside result
- return result;
- }
下面if恒为真,静态局部变量对全局可见,每次operator*返回的是它的引用,相当于是返回它的“新值”。
- bool operator==(const Rational& lhs, const Rational& rhs); // an operator== for Rationals
- Rational a, b, c, d;
- ...
- if ((a * b) == (c * d))
- {
- do whatever's appropriate when the products are equal;
- }
- else
- {
- do whatever's appropriate when they're not;
- }
3. 返回临时对象,不要定义局部对象返回
String temp(s1 + s2);
return temp;
上述代码将发生三件事。首先,temp对象被创建,同时完成初始化;然后拷贝构造函数把temp拷贝到保存返回值的外部存储单元中;最后,temp在函数结束时被销毁(调用析构函数)。然而,创建一个临时对象并返回它:return temp(s1 + s2);,编译器直接把临时对象创建并初始化在外部存储单元中,省去了拷贝和析构的化费,提高了效率。
由于内部数据类型如int,float,double的变量不存在构造函数与析构函数,虽然该“临时变量的语法”不会提高多少效率,但是程序更加简洁易读。
4. 注意不要返回栈指针和常量字符串
不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡。
- char *GetString(void)
- {
- char p[] = "hello world";
- return p; // 编译器将提出警告
- }
- void Test4(void)
- {
- char *str = NULL;
- str = GetString(); // str 的内容是垃圾
- cout<< str << endl;
- }
函数Test5运行虽然不会出错,但是函数GetString2的设计概念却是错误的。因为GetString2内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。
- char *GetString2(void)
- {
- char *p = "hello world";
- return p;
- }
- void Test5(void)
- {
- char *str = NULL;
- str = GetString2();
- cout<< str << endl;
- }
5. 谨慎返回对象内部成员对象的引用
有时候希望使得类对象占用空间较小,通常可以使用一个指向对象数据的指针作为该类的数据成员,如Rectangle类的成员指针pData。类的成员函数upperLeft和lowerRight仅仅是想获取类的数据内容而不想修改其内容,因此函数结尾使用了const表示类的数据成员不可更改。然而却不能达到设计的目的,虽然成员是私有,然而却通过公有函数返回了可以修改它的引用。如可以这样修改它:Rectangle r(&rd); r.upperLeft().setX(5);
- class Point
- {
- public:
- Point(float p1, float p2){ x = p1; y = p2; }
- void setX(float f){ x = f; }
- void setY(float f){ y = f; }
- private:
- float x, y;
- };
- struct RectData
- {
- RectData(Point p1, Point p2) : ulhc(p1), lrhc(p2){}
- Point ulhc, lrhc;
- };
- class Rectangle
- {
- public:
- Rectangle(RectData *p) { pData = p; }
- Point& upperLeft() const { return pData->ulhc; }
- Point& lowerRight() const { return pData->lrhc; }
- private:
- RectData *pData;
- };
因此需要将两函数改为,这样想试图修改点的数据内容时,编译器会报错。
- const Point& upperLeft() const { return pData->ulhc; }
- const Point& lowerRight() const { return pData->lrhc; }
- 高效率的C++函数返回值
- 高效率的C++函数返回值
- C函数的返回值
- c 函数的返回值
- C语言函数返回值的获取
- C中fread()函数的返回值
- C&C++ 函数的值返回
- 【C++】指针作为函数的返回值
- C语言 printf函数的返回值
- C语言fgetc()函数的返回值
- C main 函数的返回值
- C返回指针的函数
- 返回值为C/C++函数指针的函数
- c程序函数返回值
- C 返回函数指针的函数
- C语言的函数返回值所存放的寄存器
- 如何写出高效率的C代码
- [重要]C中fread()函数的返回值
- 扩展easyui 的表单验证
- 借我一生
- 个人整理常用注入命令
- set autot trace exp产生执行计划是否要执行sql
- iOS开发必备工具:SimpleMind轻量思维导图
- 高效率的C++函数返回值
- 分析Ext.DataView结合Ext.Panel是怎么样输出数据
- Socket的网络编程和URLDecoder类和URLEncoder类
- python按行读取文件 去掉换行符"\n"
- Random用法
- zoj 3640 Help Me Escape
- android模块编译,mm命令, 模块编译
- Cannot Initialize Data Bindings 问题解决
- AutoTRACE是分析SQL的执行计划,执行效率的一个非常简单方便的工具