我只是比较将字符串传递给函数的性能。 benchmark results很有趣。

这是我的代码:

void add(std::string msg)
{
    msg += "world";
}

void addRvalue(std::string&& msg)
{
    msg += "world";
}

void addRef(std::string& msg)
{
    msg += "world";
}

void StringCreation() {
    add(std::string("hello "));
}

void StringCopy() {
    std::string msg("hello ");
    add(msg);
}

void StringMove() {
    std::string msg("hello ");
    add(std::move(msg));
}

void StringRvalue() {
    std::string msg("hello ");
    addRvalue(std::move(msg));
}

void StringReference() {
    std::string msg("hello ");
    addRef(msg);
}

StringCreation(),StringRvalue()和StringReference()是等效的。我很惊讶StringMove()是性能最低的-比涉及复制的值传递差。

我是否认为调用StringMove()涉及一个移动构造函数,然后在调用add()时涉及一个复制构造函数,对吗?它不仅仅涉及一举一动的构造函数吗?我认为移动构造对于字符串来说是便宜的。

更新

我增加了传递给add()的字符串的长度,这确实有所作为。现在,StringMove()仅比StringCreation和StringReference慢1.1倍。 StringCopy现在是最糟糕的,这正是我所期望的。

这是新的benchmark results

因此,StringMove根本不涉及复制-仅适用于小字符串。

最佳答案

让我们分析您的代码并假设使用长字符串(未应用SSO):

void add(std::string msg) {
   msg += "world";
}

void StringCreation() {
   add(std::string("hello "));
}

在这里,首先调用来自字符串文字的转换构造函数( ConvC )以初始化临时std::string("hello ")。然后,通过移动构造函数( MC )使用此临时值(一个右值)来初始化参数msg。但是,后者很可能会通过复制删除进行优化。最后,调用运算符+=。底线: 1x ConvC和1x +=
void StringCopy() {
   std::string msg("hello ");
   add(msg);
}

在这里,参数msg由左值参数msg复制初始化(通过复制构造函数- CC )。底线: 1x ConvC,1x CC和1x += 。对于长字符串,这是最慢的版本,因为复制涉及动态内存分配(唯一的情况)。
void StringMove() {
   std::string msg("hello ");
   add(std::move(msg));
}

为什么这比StringCreation慢?仅仅是因为有一个附加的MC会初始化参数msg。不能忽略它,因为在调用msg之后,对象add仍然存在。只是它是从。底线: 1x ConvC,1x MC,1x +=
void addRef(std::string& msg) {
   msg += "world";
}

void StringReference() {
   std::string msg("hello ");
   addRef(msg);
}

此处,运算符+=应用于引用的对象,因此没有理由进行任何复制/移动。底线: 1x ConvC,1x += 。与StringCreation相同的时间。
void addRvalue(std::string&& msg) {
   msg += "world";
}

void StringRvalue() {
   std::string msg("hello ");
   addRvalue(std::move(msg));
}

使用Clang的时间与StringReference的时间相同。对于GCC,时间与StringMove相同。实际上,我目前没有这种行为的解释。 (在我看来,GCC正在创建由 MC 初始化的其他一些临时文件。但是,我不知道为什么。)

关于c++ - 通过值,引用和右值传递字符串,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57725463/

10-11 00:23