简体   繁体   English

实际使用该返回值时,如何仅支付该函数创建的返回值的成本?

[英]How do I only pay the cost of a function's created return value, when that return value is actually used?

Often times I see transformer functions that will take a parameter by reference, and also return that same parameter as a function's return value. 通常,我看到转换器函数将按引用获取参数,并且还返回与函数的返回值相同的参数。

For example: 例如:

std::string& Lowercase(std::string & str){
    std::transform(str.begin(), str.end(), str.begin(), ::tolower);
    return str;
}

I understand that this is done as a convenience, and I am under the impression that the compiler will optimize for cases when the return value is not actually used. 我知道这样做是为了方便,而且我的印象是,编译器将针对实际未使用返回值的情况进行优化。 However, I don't believe the compiler can optimize for newly created return values of non-basic types. 但是,我不相信编译器可以针对非基本类型的新创建的返回值进行优化。 For example: 例如:

std::tuple<int,std::string,float> function(int const& num, std::string const& str, float const& f){

    return std::tuple<int,std::string,float>(num,str,f);
}

Constructors could do almost anything, and although the return type isn't used, it does not mean it would be safe to avoid creating the type. 构造函数几乎可以做任何事情,尽管不使用返回类型,但这并不意味着避免创建该类型是安全的。 However, in this case, it would be advantageous to not create the type when the return value of the function isn't used. 但是,在这种情况下,当不使用函数的返回值时不创建类型将是有利的。

Is there some kind of way to notify the compiler that if the return type is not being used, it's safe to avoid the creation of the type? 是否可以通过某种方式通知编译器,如果未使用返回类型,则可以避免创建该类型吗? This would be function specific, and a decision of the programmers; 这将是特定于功能的,并且是程序员的决定; not something that the compiler could figure out on its own. 编译器无法自行解决的问题。

In the case of function and if the function is not inlined it might not optimize it since it has non trivial constructor . 对于function ,如果函数没有内联,则它可能无法优化它,因为它具有非平凡的构造函数 However, if the function is inlined it might optimize the unused return class if it's lifetime affects none of the arguments. 但是,如果函数是内联的,则在其生命周期不影响任何参数的情况下,它可能会优化未使用的返回类。 Also since tuple is a standard type i believe most compiler will optimize that returned variable. 另外,由于元组是标准类型,我相信大多数编译器都会优化返回的变量。

In general, there are two ways the compiler optimize your code: 通常,编译器可以通过两种方式优化代码:

  1. (Named) Return value optimization (RVO/NRVO) (命名)返回值优化(RVO / NRVO)
  2. R-value reference R值参考

RVO RVO

Take following code as example: 以下面的代码为例:

struct A {
    int v;
};

A foo(int v) {
    A a;
    a.v = v;
    return a;
}

void bar(A& a, int v) {
    a.v = v;
}

A f;
f = foo(1);

A b;
bar(b, 1);

In function foo , the variable a is constructed, modify its member v , and returns. 在函数foo ,将构造变量a ,修改其成员v并返回。 In an human-optimized version bar , a is passed in, modified, and gives to caller. 在人为优化的版本bara会传入,修改并提供给调用者。

Obviously, f and b are the same. 显然, fb是相同的。

And if you know more about C++, you will know in returning from foo , result a is copied to outer f , and the dtor of a is called. 而且,如果您了解更多有关C ++的知识,您将知道从foo返回时,结果a被复制到外部f ,并且将调用a的dtor。

The way to make optimized foo into bar is called RVO , it omits the copy of internal a to outer f . 使优化的foo成为bar方法称为RVO ,它省略了内部a到外部f的副本。 Modification directly goes to variable of caller. 修改直接转到调用方的变量。

Please beware, there are cases RVO won't apply: copy ctor has side effect, multiple returns, etc. 请当心,在某些情况下RVO将不适用:复制ctor具有副作用,多次退货等。

Here is a detailed explaination: 这是详细的说明:
MSDN MSDN
CppWiki CppWiki

RValue 价值

Another way to optimize return value is to use rvalue ctor introduced in C++ 11. Generally speaking, it's like calling std::swap(vector_lhs, vector_rhs) to swap the internal data pointer to avoid deep copy. 优化返回值的另一种方法是使用C ++ 11中引入的rvalue ctor 。通常来说,这就像调用std::swap(vector_lhs, vector_rhs)交换内部数据指针以避免深度复制。

Here is a very good article about optimization: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ 这是一篇关于优化的很好的文章: http : //cpp-next.com/archive/2009/08/want-speed-pass-by-value/

Last but not least 最后但并非最不重要的

In Going Native 2013 , Andrei Alexandrescu gave a talk about how to write quick C++ code. Going Native 2013中 ,Andrei Alexandrescu发表了有关如何编写快速C ++代码的演讲。 And pass by reference is faster than rvalue . 通过引用传递比rvalue更快。 (Also RVO has some limitations) So if you do care about performance, please use pass by reference. (RVO也有一些限制)因此,如果您确实关心性能,请使用通过引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM