首页 > 解决方案 > 如何在不调用复制构造函数的情况下将返回值隐式转换为基类?

问题描述

考虑两个类,例如:

#include <cstdio>

using std::puts;

class Base {
public:
    Base() { puts("Create base"); }
    Base(const Base &) { puts("Copy base"); }
    Base(Base &&) { puts("Move base"); }
    virtual ~Base() { puts("Delete base"); }
    Base & operator=(const Base &) = delete;
};

class Derived : public Base {
public:
    Derived() { puts("Create derived"); }
    Derived(const Derived &) { puts("Copy derived"); }
    Derived(const Base &) { puts("Copy derived from base"); }
    Derived(Derived &&) { puts("Move derived"); }
    Derived(Base &&) { puts("Move derived from base"); }
    virtual ~Derived() { puts("Delete derived"); }
    Derived & operator=(const Derived &) = delete;
};

和一个功能:

Base fn() {
    Derived d;
    // Fill in d here
    return d;
}

复制基类是一项非常昂贵的操作,但是由于派生类没有太大不同,因此可以使用移动语义将其转换为基对象。但是,我无法让编译器隐式使用它而不是复制构造。我尝试添加以下内容但没有成功:

Base::Base(Derived &&);
Derived::operator Base &&() &&;
Derived::operator Base() &&;

有没有办法通过只更改两个类而不是函数来避免复制构造函数fn

编辑:如果我可以更改功能,我知道该怎么做,fn但我不能。

标签: c++c++11

解决方案


Base::Base(Derived &&);如果添加正确,将正常工作。

#include <utility>

class Derived;
class Base {
  // ...
  Base(Derived &&);
};

// Derived here

Base::Base(Derived &&d) : Base(std::forward<Base>(d)) {}

唯一棘手的部分是std::forward<Base>(d). 但它最终只是一个演员表,我们要求d作为一个Basexvalue 转发。然后委托的移动构造函数做正确的事情。

现场观看

RVO 保证会尝试返回局部变量,就好像它首先是右值一样。由于现在有一个与之匹配的构造函数,因此它将起作用。


推荐阅读