首页 > 解决方案 > 在这种情况下 std::move 是否矫枉过正?

问题描述

我想知道std::move()在这个例子中使用它是否比简单地复制它是过度杀伤或计算成本更高?我真的很想知道。

class Student
{
    private: 
        std::string _studentName;
        int _studentGrade;
    public:
        Student() : _studentName("No Name"), _studentGrade(0) {}

        std::string Name() const { return _studentName; }
        void Name(std::string x) { _studentName = std::move(x); }

        int Grade() const { return _studentGrade; }
        void Grade(int x) { _studentGrade = std::move(x); }
};

标签: c++c++11

解决方案


阅读F.call 的核心指南:参数传递,我们可以得出一些建议。

仅当您想针对右值进行优化时才使用 move。如果您发现它可以提高性能,则由您决定。

您可以按值接收然后移动,因为它优化了对您的设置器的右值调用,但它使左值感到悲观。这是因为std::string从 const 引用复制时将重用其存储并且不会导致不必要的分配。当没有 SSO 可能时,复制到 value 参数总是最终分配。

首选方法,尤其是对于 setter,是使用 const 引用,并在将右值传递给 setter 时添加右值引用重载:

class Student
{
    private: 
        std::string _studentName;
        int _studentGrade;
    public:
        Student() : _studentName("No Name"), _studentGrade(0) {}

        std::string_view Name() const { return _studentName; }
        void Name(std::string const& x) { _studentName = x; }

        // add this when you need to optimize for rvalues.
        // optimizing for rvalues is not always needed.
        // They can speedup quite a bit when actually needed.
        void Name(std::string&& x) { _studentName = std::move(x); }

        // int is a trivial type, so move does nothing. No move needed.
        int Grade() const { return _studentGrade; }
        void Grade(int x) { _studentGrade = x; }
}

对于 int,std::move不会做任何事情,它仍然是一个副本。只需按值取值并按值返回即可。

但是,您能做的最好的事情要简单得多:

class Student
{
public:
    std::string studentName;
    int studentGrade;
};

由于您的设置器不强制执行任何不变量,因此您最好使用公共成员。您不需要重载和引用,因为std::string它会为您实现。


推荐阅读