c++ - 在继承层次结构中复制和移动
问题描述
考虑一个简单的
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 引用传递仍然是传统智慧
并且很可能会继续存在,请参阅有关此的代码指南。
尽管您可能在博客等上读到了什么,但您应该坚持为对象的所有正常用例传递const 引用,这些对象的复制成本可能很高 - 从语义上讲,您不必担心类型 X 如何执行移动和复制。这仍然是推荐的传统智慧,并为后期更改实施提供了所需的灵活性。如果您将代码内联留在标头中,则任何体面的编译器都可以对其进行优化(或者如果不在标头中,则可能进行整个程序优化)。
此外,对于右值而不是左值,使用复制和移动仅(有时)更快。lvalues 实际上现在更糟了,必须先获取对象的副本,然后再移动它。
std::string
由于小字符串优化,这里特别有趣
- 所以对于许多小字符串来说,在最坏的情况下可能会导致性能下降接近 2 倍。为什么?对于小字符串,移动与复制一样昂贵,移动或复制都不是微不足道的,这意味着如果使用复制和移动习语,则会出现优化失误。
在来自评论的链接中,作者还必须写:
同样,这是一种廉价的恒定时间操作,而复制是一种线性时间操作,因此在许多情况下,这是值得付出的代价。
此外,并非所有类型的移动都很便宜(示例std::array
)。
当且仅当,您已经在分析器中显示了它并且您仍然非常关心它 - 那么您可能想要使用前向引用 &&
而不是普通副本(如果不是解决方案是第三个) - 然后调用std::forward
用于转发到基类(完美转发)。
推荐阅读
- docker - 在 docker 容器中,我是 root 但 apt-get update 不起作用
- google-colaboratory - 如何在 Google Colab 上使用示例数据文件?
- c# - 是否可以在运行时限制 SQL WITHIN 查询/连接的资源?
- linux - 通过 ansible 获取 yum 更新列表失败
- javascript - 我什么时候应该使用 React 钩子?
- python - 如何在本地 Web 服务器上托管烧瓶 api?
- php - 获取用户在 Woocommerce 中购买最多的产品
- arrays - 插入排序 - 特定数组 O(n^(7/4))
- geneticsharp - 遗传夏普 - 约束下的优化
- javascript - 连接意外标识符错误PHP