我应该实现什么,SetMember(const Member&),SetMember(Member)或SetMember(Member &&)?

时间:2018-07-02 12:04:38

标签: c++ c++11 move

Memeber为一类,让我们假设我不知道它是否支持或需要移动语义。出于所有意图和目的,可以说它尚未指定/编写。我应该在具有SetMember作为成员的Outer类中实现哪种Member函数?

如果Member不支持移动,我会这样做:

class Member {
public:
    Member(Member&&) = delete;
    Member& operator=(Member&&) = delete;
};

class Outer {
    Member m_member;
public:
    void SetMember(const Member& o) { m_member = o.m_member; } // makes a copy
};

如果Member支持搬家,我会这样做:

class Member {
public:
    Member(Member&&);
    Member& operator=(Member&&);
};

class Outer {
    Member m_member;
public:
    void SetMember(Member o) { m_member = std::move(o.m_member); } // makes a copy if needed
};

但是由于我不知道它是否已移动,我是否需要同时实现两者?像这样:

class Outer {
    Member m_member;
public:
    void SetMember(const Member& o) { m_member = o.m_member; } // makes a copy
    void SetMember(Member&& o) { m_member = std::move(o.m_member); } // makes no copy
};

还是我应该这样做?

class Outer {
    Member m_member;
public:
    template <class T>
    void SetMember(T&& o) { m_member = std::forward<T>(o.m_member); }
};

为什么我对这两种解决方案不满意:

  • 在第一个解决方案中,我看到了代码重复,这仅是必需的,因为我不知道Member的某些实现细节,即它是否支持move。
  • 第二种解决方案使我每次尝试对错误类型使用SetMember时都遇到编译错误,而不是智能感知错误。我还需要一个模板,只是因为Member的一些实现细节。

处理这种情况的干净方法是什么?

1 个答案:

答案 0 :(得分:0)

据我所知,不再建议按值传值。至少在std::strings的情况下,当多次调用setter时,很有可能目标变量为新值保留了足够的内存,并且将内容复制到已分配的字符串中然后创建一个临时字符串会更便宜并移动它。
因此,无论类型是否可移动,都建议通过const引用传递并在setter内进行复制。如果以后的分析表明经常使用临时变量作为参数,并且复制的开销使其值得优化,则可能会添加右值引用的重载。
另请参见https://stackoverflow.com/a/26286741/113662