2013-07-13 35 views
17

我刚才所读经典书“有效的C++,第3版”,并在第20项笔者的结论是,内置类型,STL的迭代器和函数对象种类较多,适合传递价值。我可以很好理解内建和迭代器类型的原因,但为什么要函数对象被传递由值,因为我们知道这是无论如何类类型?为什么函数对象应该是通过按值

+2

+1看了C++有效 – Borgleader

+0

函数对象应该很少有多大的开销。 – chris

+0

至少,现在有更多的逻辑(所有对象,一般)都有移动语义。 –

回答

18

在典型的情况下,一个功能对象将有很少或(更通常)没有持久状态。在这种情况下,通过价值传递可能不需要实际传递任何东西 - 传递的“价值”基本上只是“这是对象”的占位符。

由于许多函数对象中的代码量很少,导致进一步优化:编译器通常很容易扩展函数对象的内联代码,因此没有参数传递,并且没有函数调用参与其中。

编译器可以能够当你通过指针或引用,而不是做同样的,但它不是那么容易 - 很多比较常见的,你会与对象最终被创建的,其地址传递,然后通过该指针调用该对象的函数调用操作符。

编辑:这可能也是值得一提的是,同样适用于lambda表达式,因为他们真的只是功能伪装对象。你不知道类的名字,但是他们在紧邻的作用域中创建一个类,它重载了函数调用操作符,当你“调用”lambda时被调用。 [感谢@马克西亚。]

+0

感谢您的解释,“内联优化”部分让我印象深刻。 – JavaBeta

+1

我的工作经验表明,广泛使用'boost :: bind'会导致复制的代价很高的函数对象。这似乎成倍增加绑定深度(结合具有结合内部等回调回调) –

1

从有效的STL(因为你看起来很喜欢斯科特·迈耶斯)第38项设计仿函数类用于传递值

“在C和C++中,函数指针都是按值传递的,STL函数对象是在函数指针之后建模的,所以STL中的约定是,函数对象也是在函数传递时通过值传递的。 “编辑器可以做一些优化,比如内联代码以避免函数调用(你必须将你的函数标记为内联),这有一些好处和一些暗示,像@Jerry Coffin说的。这种情况的一个很好的例子是qsort vs std :: sort性能比较,其中std :: sort使用内联函数的性能比qsort大很多,你可以在有效的STL中找到更多关于这方面的信息,这在广泛讨论并在几个章节。

这也有一些暗示,因为函数对象是通过值并返回的,所以您必须确保您的对象具有定义良好的复制机制,体积小(否则可能会变得昂贵),并且是单形的(因为按值传递多态对象可能会导致对象切片)。

+0

迈尔斯的有效串联是在中国很受欢迎:-)。另外,感谢std :: sort和std :: qsort之间的区别。 – JavaBeta

4

#1原因按值传递函数对象是因为标准库需要函数对象传递给它的算法,可拷贝。 C++ 11§25.1/ 10:

[注:除非另有规定,即采取函数对象作为参数被允许的算法复制 那些功能自由对象。对他们来说,程序员对象的身份是很重要的应该考虑使用一个指向noncopied实施对象,如reference_wrapper<T>(20.8.3), 或某些等效解决方案 包装类。 - 注意]

其他答案做了很好的解释理由。

相关问题