中易网

C++中函数返回值类型的技巧

答案:2  悬赏:80  
解决时间 2021-04-27 20:18
  • 提问者网友:浪子生来ˇ性放荡²↘
  • 2021-04-27 16:17

C/C++的函数可以通过return语句返回一个值给调用函数,而它返回时的细节是:首先将返回值拷贝到temp临时无名对象,然后删除超出作用域的对象,最后将无名对象复制到指定的接收对象中完成返回值。这里存在一个显著的性能问题:它隐式调用了拷贝构造函数。我在《C++编程思想》里面看到过解决这个问题的办法:可以在返回语句的返回值那里显式调用拷贝构造函数,如此一来就可以直接将临时对象直接设立在函数作用域之外而消除隐式调用。

C++编程思想里面有类似这样的类定义:

struct X{

int   mem;

};

X  fun(const X& test)

{

       X copy;

       copy.mem=test.mem;

       return  copy;

}

然后书上的解释说这里会导致性能损失,原因在于它在函数作用域内创建了一个对象而返回时还必须再拷贝一个临时对象,相反如果显式调用的话:

X fun(const X& test)

{

           return  X(test);

}

这里由于在return这里显式调用了构造函数,就可以指示编译器直接将临时对象创建在函数作用域之外而省去了一次调用开销。

现在的问题是:为什么在return语句中调用构造函数还是必须依赖于隐式的调用呢?换句话说,如果将拷贝构造函数声明为explicit之后,即使在return语句中直接显式调用拷贝构造函数,也还是不能通过编译。有没有什么办法消除这种无谓的性能损失?前提是不使用引用或指针,仅仅是从技术上看如何消除隐式的构造函数的调用呢?

 

最佳答案
  • 二级知识专家网友:两不相欠
  • 2021-04-27 17:38
这其实没有什么性能损失,在我测试过的编译器里,只有vc6会出现你所说“性能损失”的情形,gcc 3.3.1也只调用了2次构造和析构,而你的gcc版本更高点,所以优化到只调用一次构造和析构,这东西本质上是个编译器优化的问题,不过类似

#include <iostream>
using namespace std;

struct foo {
foo() { cout << "contructor called.\n"; }
foo(const foo& f) { cout << "copy-constructor called.\n"; }
~foo() { cout << "destructor called.\n"; }
int i;
};


foo fun(const foo& f)
{

return foo(f);
}

int main()
{
foo f(fun(foo()));
}

那句foo f(fun(foo())),不用编译器帮忙也可以看出等价于 foo f;(复制构造的话加一个参数就可以了),之所以产生那些不同时不同编译器默认优化级别的问题,我又翻了下Thinking in C++,在引用和构造函数那章,作者只说防止无用临时对象产生带来的效率损失方法有二:一是按引用传递,这对应传参,一是按引用传递然后改变实参,这对应返回,能不能说下你是在哪看到的那个消除隐式调用的方法。

至于复制构造函数声明为explicit然后在函数里return时调用出错,百度搜了下没有相关资料,c++标准文档太多,光搜一个explicit搜出几百个页,犹如大海捞针,然后我跑去google comp.lang.c++新闻组问问题,由于英文太烂,也没得到几个合适的答复,不过某热心的老外说,explicit就是防止隐式转换,而return的时候调用复制构造其实就包含了隐式转换,我正在等待他对此的详细解答,和你一起关注。。。
全部回答
  • 1楼网友:狠傷凤凰
  • 2021-04-27 19:14

建议你看看这个

http://soft.yesky.com/440/2052440.shtml

我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息!
大家都在看
推荐信息