将参数移动到数据成员:通过复制或 rvalue-ref 获取参数?

Moving parameter to data member: Take parameter by copy or rvalue-ref?

提问人:glades 提问时间:2/9/2023 更新时间:2/9/2023 访问量:61

问:

我有一个类对象,它吞噬一个字符串并将其推入构造时的成员中(为了这个论点,它可以是任何旧成员函数)。entity

现在我至少可以通过两种方式做到这一点:我可能会接受一个 std::string 副本并将其移动到成员 () 中。但是,我也可以直接采用 rvalue-ref 并继续移动到数据成员 ()。inefficient_entityefficient_entity

两者之间有性能差异吗?我问 bc 通过复制并让调用站点决定是否要移动或复制字符串更方便。另一种方式是,我可能需要创建一个重载集,该重载集可以增长到大量,因为我的构造函数也可以以相同的方式接受多个参数。

无论如何,这都会被优化出来还是我必须担心?

演示

#include <string>
#include <cstdio>

struct efficient_entity
{
    efficient_entity(std::string&& str)
        :   str_ { std::move(str) }
    { }

    std::string str_;
};

struct inefficient_entity
{
    inefficient_entity(std::string str)
        :   str_ { std::move(str) }
    { }

    std::string str_;
};


int main()
{
    std::string create_here = "I guarantee you this string is absolutely huge!";
    efficient_entity(std::move(create_here));
    inefficient_entity(std::move(create_here));
}

注意:Afaik 有一个关于 cppcon 的演讲,其中完全涵盖了这一点,但我再也找不到它了(如果有人可以给出提示,请表示感谢)。

C++ 移动语义 rvalue-reference 类-方法 函数-参数

评论

1赞 BoP 2/9/2023
没有一个放之四海而皆准的解决方案,因为那样我们就只会使用那个。“有效”的假设你总是想移动 - 如果原始字符串是 const 怎么办?然后你得到一个副本和一个动作,而你本可以只得到一个副本。这有那么重要吗?这是一个工程问题,由您决定。什么时候“足够好”比“完美”好?

答:

2赞 HolyBlackCat 2/9/2023 #1

按值传递会花费您多走一步。

另一方面,通过引用传递需要您编写两个函数:或 。或 N 个参数的 2 个N 个函数,或一个模板。const T &T &&

默认情况下,我更喜欢第一个,并在应该很快的低级实用程序中使用第二个。


只有一个过载是可行的,但非常非正统。这仅为您提供一个额外的移动,这些副本必须写成(或在 C++23 中)。T &&func(std::string(value))func(auto(value))

这里所谓的好处是所有副本都是显式的。我只对重型类型这样做,而且只有当你喜欢这种风格时。