【问题标题】:Should move semantics be used in constructor chains?构造函数链中应该使用移动语义吗?
【发布时间】:2013-03-16 12:41:02
【问题描述】:

假设我有以下两个类:

class Person
{
    public:
        Person(string name, string surname)
            : _name(move(name)), _surname(move(surname)) { }
        ...
    private:
        string _name;
        string _surname;
};

class Student : public Person
{
    public:
        Student(string name, string surname, Schedule schedule)
            : Person(move(name), move(surname)), _schedule(move(schedule)) { }
        ...
    private:
        Schedule _schedule;
};

int main()
{
    Student s("Test", "Subject", Schedule(...));
    ...
    return 0;
}

这是对移动语义的一种很好的用法吗?如您所见,Student 构造函数中有一层“move-s”。如果不使用const 引用将参数转发给基构造函数,是否可以避免move 函数调用开销?

或者也许..当我需要将参数转发给基本构造函数时,我应该使用 const 引用吗?

【问题讨论】:

    标签: c++ c++11 move-semantics


    【解决方案1】:

    没有。只有非常大的类型才能获得性能提升,这非常很少见。当然,当处理一些你事先不知道的移动非常昂贵或不可移动的类型时,请假设便宜的移动。

    您现有的代码是惯用的 C++11,在这方面完美的转发构造函数是错误的,并且会因为一个参数启动而严重破坏事情。

    【讨论】:

    • Going Native 2012 的 OP 的好视频 - STL11: Magic && Secrets - 查看 33:45 标记以通过价值与参考。
    • @CaptainObvlious 可以。谢谢。
    【解决方案2】:

    在选择优化之前考虑优先考虑代码的可读性和简单性。您很可能不需要在一次复制/移动操作上保存,在这种情况下,您应该倾向于清晰和简单(例如参考const)。

    这就是说,如果您担心转发构造函数参数的开销,您可以将构造函数设为构造函数模板并使用完美转发来产生最小开销无论您传递的是右值还是左值:

    class Person
    {
        public:
            template<typename T, typename U>
            Person(T&& name, U&& surname)
                : _name(std::forward<T>(name)), _surname(std::forward<U>(surname)) { }
            ...
        private:
            string _name;
            string _surname;
    };
    
    class Student : public Person
    {
        public:
            template<typename T, typename U, typename V>
            Student(T&& name, U&& surname, V&& schedule)
                : Person(
                    std::forward<T>(name), 
                    std::forward<U>(surname)), 
                    _schedule(std::forward<V>(schedule)) 
            { }
            ...
        private:
            Schedule _schedule;
    };
    

    【讨论】:

    • 这有什么比老式的、简单的方式更好的呢?
    • @JohnZwinck:它避免了不必要的复制/移动
    • @JohnZwinck 除了 Andy 刚才所说的之外,它还使您无需为多参数构造函数提供 const T&amp;T&amp;&amp; 的所有组合。
    • 越是看到这样的C++,越想用其他语言代替。什么样的恶梦!我是作为一个长期的 C++(甚至 C++11)用户说的。
    • @AndyProwl:我明白了……谢谢你的建议。对于我当前的用例,我想我会继续通过 const 引用传递,因为代码可读性具有更高的优先级。
    猜你喜欢
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 2012-06-12
    • 2018-05-08
    相关资源
    最近更新 更多