问一个函数按值返回和按引用返回的性能问题和解决办法
第一种按值返回:
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
[解决办法]
顶 我也想知道能满足方法
[解决办法]
无能为力.
[解决办法]
一般编译器会做优化。
[解决办法]
[code=C/C++][/code]
Type* fun()
{
Type a;
Type *p = &a;
return p;
}
int main()
{
fun();
return 0;
}
你应该用返回指针的方法获得对象
[解决办法]
楼上回家再读几年书,别误导人了.
[解决办法]
楼主还是先搞清一个基本概念:对象的生命周期。
你的要求是返回非静态局部对象的引用,并绕开对象生命周期的问题,这是在错误应用的基础上玩技巧。
使用C++,首先应该考虑其正确的使用方式,而不是搞所谓的语法语义的“创新”,尤其是前提错误的情况下。
至于效率问题,楼主最需要知道的是80-20法则,即使你这样达到了你的目的,你的程序的效率也提高不了,况且对于返回对象的方式(第一种方式),现代编译器都会优化,google“RVO”与“NRVO”(返回值优化)吧。
[解决办法]
你不觉得楼主是在推进新的C++标准进程吗-__-b
[解决办法]
被弄郁闷了啊,今天吃火药了。。。。
[解决办法]
返回一个对象不叫创新,可你不是要求返回局部对象的引用,且阻止局部对象的析构被调用吗?
你举例的这段代码是典型的可以施行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 的右值引用特性了……
前两天试图模拟实现一个稍微通用点的右值引用类型,结果果断悲剧……
[解决办法]
学习下。。。。。。。。。。。。。。。。
[解决办法]
+++++++++++
[解决办法]
我觉得这样挺好的。
如果不要求每次调用构造函数,我觉得那种static变量方法也挺好的。
你要每次调用构造,而不被析构,智能new了,然后自己管理指针防止内存泄露。其实就是智能指针了,标准库的智能指针就挺好的。
[解决办法]
一个示例和相关说明:
http://topic.csdn.net/u/20091027/00/112644cb-231c-43a0-a700-bddd5eb6a4cd.html。
[解决办法]
建议返回一个类成员变量或者静态变量的引用
[解决办法]
那看起来还是用std::auto_ptr比较现实一点。
用mojo实现右值引用的源码Google了一下没找到,orz……而且比起来更复杂。