C ++ 11:通过值调用,移动语义和继承 [英] C++11: call by value, move semantics and inheritance

查看:126
本文介绍了C ++ 11:通过值调用,移动语义和继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个类,我计划直接暴露作为一个可实例化类
给程序员:

Let's say I have a class which I plan to directly expose as an instantiatable class to the programmer:

class Base
{
public:
    Base(std::string text) : m_text(std::move(text)) {}
private:
    std::string m_text;
};

到目前为止很好。这里不需要一个右值构造函数。
现在,在将来的某个时候,我决定扩展Base:

So far so good. No need for a rvalue-constructor here. Now, at some point in the future, I decide to extend Base:

class Derived : public Base
{
public:
    Derived(const std::string &text) : Base(text) {}
};

这个错误让我不能接受Derived中的字符串值,因为这是
基地已经在做 - 我最终有2副本和1移动。这里的const引用构造函数也对右值执行一个不必要的副本。

This bugs me: I can't take the string by value in Derived because that's what Base is already doing - I'd end up with 2 copies and 1 move. The const-reference constructor here also performs an unnecessary copy on rvalues.

问题:如何复制+移动一次(像Base中的简单构造函数)添加更多构造函数?

The question: how do I copy + move only once (like the simple constructor in Base did) without adding more constructors?

推荐答案

只能复制和移动一次,除非您更改类的设计,构造函数(可能是SFINAE约束)模板化转发构造函数( Yakk的回答显示了如何)。

You can't copy and move only once, unless you change the design of your classes and turn their constructors into (possibly SFINAE-constrained) templated forwarding constructors (Yakk's answer shows how).

这样做可以使得在提供右值时只执行一次移动和没有副本,在提供左值时只有一个副本,没有移动。在大多数情况下,这是一个过度的。

While doing that would make it possible to perform just one move and no copy when rvalues are provided, and one copy and no moves when lvalues are provided, it is an overkill in most situations.

作为基于模板的转发构造函数的替代方法,您可以在基类和派生类中提供两个构造函数:一个用于右值引用和一个用于对 const 的左值引用。但是,在大多数情况下,这是一个不必要的复杂性(当参数数量增加时,扩展性不好,因为所需的构造函数数量将呈指数增长)。

As an alternative to the template-based forwarding constructors, you could provide two constructors, both in your base class and in your derived class: one for rvalue references and one for lvalue references to const. But again, that's an unnecessary complication in most scenarios (and doesn't scale well when the number of arguments increases, since the number of required constructors would increase exponentially).

移动 std :: string 与复制指针和整数一样快(忽略SSO优化),你不应该麻烦它,除非你有真实的证据,

Moving an std::string is as fast as copying a pointer and an integer (ignoring SSO optimization here), and you should not bother about it unless you have real evidence that this is a bottleneck that prevents your application from meeting its performance requirements (hard to believe).

因此,只需让您的派生构造函数以无条件的方式接受其值,并将其传递给基类的构造函数时移动它:

Therefore, just let your Derived constructor take its argument by value unconditionally, and move it when passing it to the base class's constructor:

class Derived : public Base
{
public:
    Derived(std::string text) : Base(std::move(text)) { }
};

另一个选项,如果你想要(或接受) Derive 继承 Base 的构造函数,是利用C ++ 11继承的构造函数,如下所示:

Another option, in case you want (or accept) Derive to inherit all of Base's constructors, is to exploit C++11's inherited constructors like so:

class Derived : public Base
{
public:
    using Base::Base;
//  ^^^^^^^^^^^^^^^^^
};

这篇关于C ++ 11:通过值调用,移动语义和继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆