当您打算存储对象时,我对“按值接受”的“规则”感到满意,而当您只需要访问它时,通过 const 引用接受。这样,您(类的编写者)不会选择是复制类变量的用户还是移动它,他们会选择。但在使用过程中,我越来越不确定该建议是否合理。move在成本操作中不是统一的...
struct Thing
{
std::array<int, 10000> m_BigArray;
};
class Doer
{
public:
Doer(Thing thing) : m_Thing(std::move(thing)) {}
private:
Thing m_Thing;
};
int main()
{
Thing thing;
Doer doer1(std::move(thing)); // user can decide to move 'thing'
// or
Doer doer2(thing); // user can decide to copy 'thing'
}
在上面的示例中,移动与复制一样昂贵。因此,您最终会移动它(有效地复制它)两次,而不是获取一个 const 引用并复制一次对象。用户在您的论点中执行一次,您在您的成员中再次执行。
即使移动比复制便宜得多,这种情况也会进一步恶化(假设移动的成本低于某些未知成本,但比复制便宜):
struct A
{
A(Thing thing) : m_Thing(std::move(thing)) {}
Thing m_Thing;
};
struct B : A
{
B(Thing thing) : A(std::move(thing)) {}
};
struct C : B
{
C(Thing thing) : B(std::move(thing)) {}
};
struct D : C
{
D(Thing thing) : C(std::move(thing)) {}
};
在这里,您要么以 1 个副本和 4 个动作结束,要么以 5 个动作结束。如果所有构造函数都接受一个 const 引用,那么它只会是 1 个副本。现在我必须权衡什么是昂贵的移动,1 副本或 5 移动。
处理这些情况的最佳建议是什么?