在继承层次结构中复制和移动

Copy and move through inheritance hierarchy

本文关键字:移动 复制 继承 层次结构      更新时间:2023-10-16

考虑一个简单的

class Foo
{
public:
Foo(const std::string& name) : _name{name}
private:
std::string _name;
};

我们知道可以通过复制和移动进行优化

class Foo
{
public:
Foo(std::string name) : _name{std::move(name)}
private:
std::string _name;
};

但现在考虑一下层次结构:

class Base
{
protected:
Base(const std::string& name) : _name{name}
private:
std::string _name;
};
class Derived : public Base
{
public:
Derived(const std::string& name) : A(name) {}
};
class Derived2 : public Derived
{
public:
Derived2(const std::string& name) : Derived(name) {}
};

在这里实现复制和交换习惯用法的正确方法是什么?使用复制和交换而不是传递const引用是否有意义?

编辑:请解释否决票。

通过const-reference仍然是传统智慧

而且在所有可能的情况下都会继续,请参阅与此相关的代码指南。

不管你在博客等上读到了什么,你都应该坚持为所有复制成本可能很高的对象的正常用例传递const引用——从语义上讲,你不需要担心X类型如何执行移动和复制。这仍然是推荐的传统智慧,并为后期更改实现提供了所需的灵活性。如果将代码内联在头中,那么任何优秀的编译器都可以优化它(如果不在头中的话,也可以使用整个程序优化(。

此外,使用复制和移动只是(有时(对右值更快,而不是对左值。lvalues现在的情况实际上更糟了,必须先复制一个对象,然后再移动它

std::string在这里特别有趣,因为小字符串优化-所以对于许多小字符串来说,在最坏的情况下,性能下降接近2倍。为什么?对于小字符串,移动和复制一样昂贵,移动或复制都不是微不足道的,这意味着如果使用复制和移动习惯用法,则会错过优化。

在链接到commments的帖子中,作者还必须写道:

同样,这是一种廉价的恒定时间操作,而复制是一种线性时间运算,因此在许多情况下这将是一个很好的价格值得付出。

此外,并非所有类型的移动都很便宜(例如std::array(。

如果并且仅当,您已经在探查器中显示了这一点,并且您仍然非常关注它-那么您可能希望使用转发引用&&而不是纯副本(如果不是,则解决方案是第三方(-然后调用std::forward来转发到基类(完美转发(。