请考虑以下两个类:
#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
,但我做不到,我知道该怎么做。
答案 0 :(得分:1)
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
作为Base
xvalue转发。然后委派的move构造函数执行正确的操作。
保证RVO尝试返回本地变量,就好像它首先是右值一样。由于现在有一个与之匹配的构造函数,它将可以正常工作。