1

哪些 set 方法在支持右值的编译器中具有更好的性能:有或没有const&?例如

class A
{
public:
    void setProperty(Property const& p)   {m_property = p;}
    void setProperty(Property p)          {m_property = p;}
};

还是两者都可以?这Property是一个大班。Visual Assist X 中的重构工具使用第二个没有const&.

4

5 回答 5

4

编写 setter 以获取const&

void setProperty(Property const& p) {m_property = p;}

在 C++11 中,编写一个也需要的重载&&

void setProperty(Property&& p) {m_property = std::move(p);}

使用“快捷方式”方法编写一个按值获取属性的单个重载是很好的:

void setProperty(Property p) {m_property = std::move(p);}

但请注意,当传递一个左值时,这需要在短时间内同时为 3 个对象(原始对象、成员和参数)分配内存。

如果您感觉特别轻松,您可以通过编写一个完美的转发设置器来让您的朋友和家人感到惊讶:

template <typename T>
void setProperty(T&& t) {m_property = std::forward<T>(t);}

它包含 theconst&&&case,并且能够接受任何可分配给 的类型m_property。请注意,这对可读性很不利,并且在滥用时会导致“有趣”的错误消息。

于 2013-07-29T02:55:18.787 回答
2

这个更好

void setProperty(Property const& p)   {m_property = p;}

它在进入 setProperty 函数时保存一份副本Property,它只复制一个Property非常便宜的引用。

于 2013-07-29T02:25:01.850 回答
1

这个问题只能通过查看Property类型来回答。如果它实现了移动操作,那么最好的方法是按值获取参数并在内部移动它:

void setProperty(Property p)   {m_property = std::move(p);}

如果参数是左值,则复制将在接口中完成,并且您将在内部移动该值,并且成本将是一份副本和一次搬家(搬家应该是便宜的)。如果函数的参数是临时的,编译器可以省略副本(如果没有,它必须移动而不是复制)。然后,该函数将在内部执行另一次移动,总成本为一个(或两个)移动操作,这很便宜。

如果您通过了const&,那么在参数是临时参数的情况下,编译器将无法删除副本,您将支付两份副本的费用。

关于使用完美转发的建议,如果您可以访问该 Property类型的接口(您应该访问该类型的接口,因为您拥有一个成员),则无需将 setter 设置为模板,因为这会在其他维护者的最终可执行文件和不必要的复杂性。

于 2013-07-29T03:36:04.507 回答
0

一般来说,通过引用传递是最好的,因为它节省了复制对象。如果对象很小且复制行为很简单(具有一些整数和默认复制构造函数),则复制对象的成本可以忽略不计。在某些情况下,按值传递可能会更快,因为优化器知道没有其他东西可以修改函数接收到的对象。因为我不知道 Property 是什么,所以如果它是一个大型或复杂的类,我会通过引用传递。如有疑问,请通过参考。

在 C++11 中,由于移动构造函数和其他东西,事情可能会有所不同,但我并不完全理解它们。但是你不会对这个建议大错特错。如有疑问,请通过参考!

于 2013-07-29T02:44:10.893 回答
0

当你使用一个常量引用时,你只发送一个指向函数的指针,而不是复制整个对象(类属性)。这可以为您节省一些时间,尤其是在物业很大的情况下。更重要的是,它可以为您节省宝贵的内存。

但是,由于 const&,您不能进行任何更改。如果删除 const,将对原始对象进行任何更改。

总而言之,如果您只想从 Property Object 获取信息而不进行任何更改,那么常量引用 (const&) 是最好的方法。

于 2013-07-29T02:36:25.723 回答