首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

问一个函数按值返回和按引用返回的性能有关问题和解决方法

2013-04-07 
问一个函数按值返回和按引用返回的性能问题和解决办法第一种按值返回:Type fun(){Type t.....return t /

问一个函数按值返回和按引用返回的性能问题和解决办法
第一种按值返回:
Type fun()
{
    Type t;
    .....
    return t; // 返回时会构造一个新的Type并返回此新对象,并调用t的析构函数
}


第二种按引用返回:
Type& fun()
{
    Type t;
    .....
    return t; // 返回T的地址,但还是会调用t的析构函数

}


第一种结果虽然正确,可是浪费了一个对象的构造和析构过程,
第二种虽然返回了地址,可是对象已经被释放了,也就是结果不对

现在我想问,我采用第二种方式来写项目中的大部分的函数,那怎么确保每次调用这个函数时,
T的构造函数会被调用, 但不会调用t的析构函数.





[解决办法]


//用这种好了
Type& fun(Type& t)
{
  
  .....
  return t; // 返回T的地址,但还是会调用t的析构函数

}

//或者这样
Type& fun()
{
  static Type t;
  .....
  return t; // 返回T的地址,但还是会调用t的析构函数

}

[解决办法]
#include <iostream>
#include <string>
#include <memory>
using namespace std;

template <class T>
auto_ptr<T> func(const T &obj)
{
return auto_ptr<T>( new T(obj) );
}

int main()
{
string hello="Hello World";
auto_ptr<string> p=func(hello);
cout<<hello<<endl;
return 0;
}

[解决办法]
#include <iostream>
#include <string>
#include <memory>
using namespace std;

template <class T>
auto_ptr<T> func(const T &obj)
{
return auto_ptr<T>( new T(obj) );
}

int main()
{
string hello="Hello World";
auto_ptr<string> p=func(hello);
cout<<*p<<endl;
return 0;
}

[解决办法]
请看第二个回复,第一个没意义.
[解决办法]
感觉要满足你的要求需要编译器升级-_-b
[解决办法]
引用:
感觉要满足你的要求需要编译器升级-_-b

顶 我也想知道能满足方法
[解决办法]
无能为力.
[解决办法]
一般编译器会做优化。
[解决办法]
[code=C/C++]
Type* fun()
{
Type a;
Type *p = &a;
return p;
}

int main()
{
fun();
return 0;
}
你应该用返回指针的方法获得对象


[/code]
[解决办法]
楼上回家再读几年书,别误导人了.
[解决办法]
楼主还是先搞清一个基本概念:对象的生命周期。

你的要求是返回非静态局部对象的引用,并绕开对象生命周期的问题,这是在错误应用的基础上玩技巧。

使用C++,首先应该考虑其正确的使用方式,而不是搞所谓的语法语义的“创新”,尤其是前提错误的情况下。



至于效率问题,楼主最需要知道的是80-20法则,即使你这样达到了你的目的,你的程序的效率也提高不了,况且对于返回对象的方式(第一种方式),现代编译器都会优化,google“RVO”与“NRVO”(返回值优化)吧。
[解决办法]

引用:
引用:
感觉要满足你的要求需要编译器升级-_-b

顶 我也想知道能满足方法


你不觉得楼主是在推进新的C++标准进程吗-__-b
[解决办法]
引用:
楼上回家再读几年书,别误导人了.

被弄郁闷了啊,今天吃火药了。。。。
[解决办法]
引用:
返回一个对象也叫创新啊?

还有你说的效率提高不了多少,
以第一种方法来说,一个连接字符串的函数并返回结果
string cat(string a, string b)
{
  string s = a + b;

  /*

  前面性能都一样

  */

  return s;  
  /* 这里的话,假设s的结果长度为 1G, 那么创建一个对象s2, 分配 1g的空间,没有剩余空间,程序就挂了
  有的话,分配了,然后释放s 的空间, 返回 s2.

何必呢? 为什么不直接可以返回 s ?
  */
}

返回一个对象不叫创新,可你不是要求返回局部对象的引用,且阻止局部对象的析构被调用吗?

你举例的这段代码是典型的可以施行NRVO的代码,且不考虑string是引用计数的,你又是怎么得出编译器会创建一个s2的拷贝并说程序挂了?
string cat(string a, string b)
{
  string s = a + b;

  /*

  前面性能都一样

  */

  return s;  
  /* 这里的话,假设s的结果长度为 1G, 那么创建一个对象s2, 分配 1g的空间,没有剩余空间,程序就挂了
  有的话,分配了,然后释放s 的空间, 返回 s2.

何必呢? 为什么不直接可以返回 s ?
  */  这段话你是自己想像的,还是从哪里看来的,你试过了?不要想当然。
}

[解决办法]
其实是缺乏move语义的原因。A. Alexandrescu很早就提出过这一点,并用复杂的模板技巧在一定程度上进行了实现,可以参考Loki里的yasli::vector。
C++0x引入move语义,使用右值引用解决这个问题。
[解决办法]
对于复杂函数,不能施行返回值优化时,也不要想着怎么返回一个局部对象的引用(这几乎总是不正确的),你完全可以将影响性能的对象作为引用或指针型参数来传递。
[解决办法]
构造函数和析构函数会被编译器确保成对调用,这是C++引入构造函数、析构函数的目的

换句话说,构造函数和析构函数就是设计来成对调用的,而且还是要求编译器必须确保的东西

另外,还有一些其他的C++特性依赖于这个成对调用

编译器的确会做一些优化,但也是成对的优化掉,不会做不对称的优化

如果LZ非要推翻这个根基,那么请抛弃C++。。

细节请参考《C++语言的设计和演变》

[解决办法]
看effective c++吧,该返回值时就不要返回引用指针之类的东西
[解决办法]
引用:
引用:
对于复杂函数,不能施行返回值优化时,也不要想着怎么返回一个局部对象的引用(这几乎总是不正确的),你完全可以将影响性能的对象作为引用或指针型参数来传递。


我也想返回指针,问题调用之后还要释放..


不是返回值,是参数传递。
[解决办法]
第二种往往做成单件类,也就是实例化一个静态的对象。
[解决办法]
void cat(string * result, const string& a, const string& b)
{
    *result += a + b;
}

string a("Hello, ");
string b("world!");
string str;
cat(&str, a, b);
[解决办法]
你们的设计就如此限定的?
如果限定为必须返回局部对象,那么也别考虑返回其引用(正确性是第一位的),考虑一下对这个对象类做改造吧(如引用计数之类,即浅复制)。
------解决方案--------------------


路过。

楼主要是真想彻底解决这个问题恐怕还是要用到 C++0x 的右值引用特性了……

前两天试图模拟实现一个稍微通用点的右值引用类型,结果果断悲剧……
[解决办法]
学习下。。。。。。。。。。。。。。。。

[解决办法]

引用:
楼主还是先搞清一个基本概念:对象的生命周期。

你的要求是返回非静态局部对象的引用,并绕开对象生命周期的问题,这是在错误应用的基础上玩技巧。

使用C++,首先应该考虑其正确的使用方式,而不是搞所谓的语法语义的“创新”,尤其是前提错误的情况下。

至于效率问题,楼主最需要知道的是80-20法则,即使你这样达到了你的目的,你的程序的效率也提高不了,况且对于返回对象的方式(第一种方式),……


+++++++++++
[解决办法]
引用:
C/C++ code
#include <iostream>
#include <string>
#include <memory>
using namespace std;

template <class T>
auto_ptr<T> func(const T &amp;obj)
{
    return auto_ptr<T>( new T(obj) );
}

int main()
{……


我觉得这样挺好的。
如果不要求每次调用构造函数,我觉得那种static变量方法也挺好的。
你要每次调用构造,而不被析构,智能new了,然后自己管理指针防止内存泄露。其实就是智能指针了,标准库的智能指针就挺好的。
[解决办法]
引用:
能具体点给点代码么?看不明白

一个示例和相关说明:
http://topic.csdn.net/u/20091027/00/112644cb-231c-43a0-a700-bddd5eb6a4cd.html。


[解决办法]
建议返回一个类成员变量或者静态变量的引用
[解决办法]
引用:
lsd,那个要2010,通用性不太好

我用的是vs2005,

那看起来还是用std::auto_ptr比较现实一点。
用mojo实现右值引用的源码Google了一下没找到,orz……而且比起来更复杂。

热点排行