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

Copy and move through inheritance hierarchy

考虑一个简单的

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传递仍然是常识

并且将总共 likely-hood 继续 see code guidelines 关于这件事。

不管你在博客等上读到什么,你应该坚持为所有正常用例传递常量引用 objects 的复制成本可能很高——从语义上讲,您不必担心 X 类型如何明智地执行移动和复制。这仍然是推荐的传统智慧 并提供了在稍后阶段更改实现所需的灵活性 。如果您将代码留在 header 中,任何体面的编译器都能够 optimize that anyway(或者如果不在 header 中,则可能对整个程序进行优化)。

此外,使用复制和移动只是(有时)对右值更快 - 而不是左值。左值实际上现在更糟了,必须先复制 object 然后再移动它。

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

在链接到post的评论中,作者还要写:

That, again, is a cheap constant-time operation, whereas copying is a linear-time operation, so in many cases that will be a price well worth paying.

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

当且仅当,你已经将它显示在分析器中并且你仍然真的真的关心它 - 那么你可能想使用 forward reference && 而不是普通副本(如果不是解决方案是第三种) - 然后调用 std::forward 转发到 base 类 (完美转发).