为了从函数中返回字符串,这两个函数中的哪一个效率更高(即,我应该使用哪个):

std::string f(const std::string& s)
{
    return s + "some text";
}

要么
void f(const std::string& s, std::string &result)
{
    result = s + "some text";
}

我知道答案可能取决于特定的编译器。但是我想知道现代C++代码中推荐的方法(如果有的话)是什么。

根据下面的“轨道中的轻度竞赛”评论,这是我问这个问题之前在stackoverflow上发现的一些相关问题:

Are the days of passing const std::string & as a parameter over?

Passing std::string by Value or Reference

Pass by value or const reference?

"std::string" or "const std::string&" argument? (the argument is internally copied and modified)

没有一个人回答我关于从函数返回值与将字符串作为额外参数返回的特定问题。

最佳答案

让我微优化您的第二个版本f()并将其称为g():

#include <cstdio>
#include <string>
using namespace std;

string f(const string& s) {
    return s + "some text";
}

void g(const string& s, string &result) {
    result.clear();
    result += s;
    result += "some text";
}

现在,让我们将“按值返回”方法f()与“输出参数”方法g()进行比较。

按值返回:
int main(int argc, char* argv[]) {

    string s(argv[1]);

    for (int i=0; i<10; ++i) {

      string temp = f(s); // at least 1 memory allocation in each iteration, ouch!

      fprintf(stderr, "%s\n", temp.c_str());
    }
}

在每个迭代中,都有一个内存分配。分配的总数将为迭代次数+ 1,在这种情况下为11。

“超出参数”方法:
int main(int argc, char* argv[]) {

    string s(argv[1]);

    string temp; // note that this time, it is outside the loop

    for (int i=0; i<10; ++i) {

      g(s, temp);

      fprintf(stderr, "%s\n", temp.c_str());
    }
}

在这种情况下,即使您迭代1000000次,您也会获得3个内存分配(假设temp的缓冲区不需要在循环内重新分配)!与按值(value)返回法相比,这是一个重大改进。

按值返回并依赖复制删除或移动语义是一个很好的建议,但是如示例所示,在某些情况下,超出参数的方法会赢得(例如,当您可以重新使用缓冲区时)。

参数外的危险在于,在调用站点处,仅通过查看代码,就必须显而易见该函数正在修改其某些参数。函数的名称必须强烈暗示它正在变异其某些参数。否则,您会得到令人惊讶的结果... :(

如果您发现此示例过于扭曲,那就不是:想想std::getline()!

对于那些认为这是过早优化的人:如果是std::getline(),则肯定不是! 如果将文件的各行推入std::vector并为每行分配一个新的字符串,它将比参数外方法(每行80字节)慢1.6倍。听起来很疯狂,因为文件IO应该是瓶颈,但不是,这是不必要的内存分配。有关详细信息,请在48分钟左右查看Andrei Alexandrescu: Writing Quick Code in C++, Quickly


更新:
  • R. Martinho Fernandes在下面的评论中友善地指出,他的测量
    gcc与我的结果相反,但与我的主张一致
    clang和libc++;看到
    GCC

    Clang
  • 他指出这些之后,我对Andrei进行了测量
    Alexandrescu的例子。目前,我无法复制他的
    结果;它需要进一步分析,以了解在
    罩。

  • 请耐心等待,请给我一些时间来消除不一致之处。

    这个故事的重点是要始终衡量。 我确实测量了答案中提到的内存分配数量,但这仍然可以(至少在我的机器上)。

    关于c++ - 应该从函数值中返回std::string还是由 “std::string &s”作为参数返回?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21636248/

    10-12 00:24
    查看更多