Sve*_*ing 123 c++ reference function
假设我有一个函数,它需要std::function
:
void callFunction(std::function<void()> x)
{
x();
}
Run Code Online (Sandbox Code Playgroud)
我应该x
通过const-reference来代替吗?:
void callFunction(const std::function<void()>& x)
{
x();
}
Run Code Online (Sandbox Code Playgroud)
这个问题的答案是否会根据函数的作用而改变?例如,如果它是一个类成员函数或构造函数,它存储或初始化std::function
成成员变量.
Yak*_*ont 67
如果您想要性能,请在存储时按值传递.
假设您有一个名为"在UI线程中运行此函数"的函数.
std::future<void> run_in_ui_thread( std::function<void()> )
Run Code Online (Sandbox Code Playgroud)
它在"ui"线程中运行一些代码,然后future
在完成时发出信号.(在UI框架中很有用,其中UI线程是你应该弄乱UI元素的地方)
我们正在考虑两个签名:
std::future<void> run_in_ui_thread( std::function<void()> ) // (A)
std::future<void> run_in_ui_thread( std::function<void()> const& ) // (B)
Run Code Online (Sandbox Code Playgroud)
现在,我们可能会使用如下:
run_in_ui_thread( [=]{
// code goes here
} ).wait();
Run Code Online (Sandbox Code Playgroud)
这将创建一个匿名闭包(lambda),构造一个std::function
,将其传递给run_in_ui_thread
函数,然后等待它在主线程中完成运行.
在情况(A)中,std::function
直接由我们的lambda构造,然后在lambda中使用run_in_ui_thread
.lambda move
d进入std::function
,所以任何可移动的状态都有效地进入它.
在第二种情况下,std::function
创建一个临时值,将lambda move
放入其中,然后std::function
通过引用使用临时值run_in_ui_thread
.
到目前为止,这么好 - 他们两个表现相同.除了run_in_ui_thread
要将其函数参数的副本发送到ui线程执行之外!(它将在完成之前返回,因此它不能仅使用对它的引用).对于情况(A),我们简单move
的std::function
将其长期储存.在情况(B)中,我们被迫复制std::function
.
该商店使价值传递更加优化.如果您有可能存储副本std::function
,则按值传递.否则,任何一种方式都大致相同:按值的唯一缺点是,如果你采用相同的体积std::function
并且使用一种子方法接着使用它.除此之外,a move
和a一样高效const&
.
现在,如果我们内部存在持久状态,那么两者之间还存在一些其他差异std::function
.
假设std::function
存储一些具有a的对象operator() const
,但它也有一些mutable
它修改的数据成员(多么粗鲁!).
在这种std::function<> const&
情况下,mutable
修改的数据成员将传播出函数调用.在这种std::function<>
情况下,他们不会.
这是一个相对奇怪的角落案例.
你想像std::function
任何其他可能重量级,便宜的移动类型一样对待.移动很便宜,复制可能很昂贵.
Ben*_*igt 31
如果您担心性能,并且没有定义虚拟成员函数,那么您很可能根本不应该使用它std::function
.
使仿函数类型成为模板参数允许更大的优化std::function
,包括内联仿函数逻辑.这些优化的效果可能大大超过了复制与间接关于如何传递的问题std::function
.
快点:
template<typename Functor>
void callFunction(Functor&& x)
{
x();
}
Run Code Online (Sandbox Code Playgroud)
sya*_*yam 24
像往常一样在C++ 11中,传递value/reference/const-reference取决于你对你的参数做什么.std::function
没有什么不同.
按值传递允许您将参数移动到变量(通常是类的成员变量):
struct Foo {
Foo(Object o) : m_o(std::move(o)) {}
Object m_o;
};
Run Code Online (Sandbox Code Playgroud)
当您知道您的函数将移动其参数时,这是最佳解决方案,这样您的用户就可以控制他们调用您的函数的方式:
Foo f1{Object()}; // move the temporary, followed by a move in the constructor
Foo f2{some_object}; // copy the object, followed by a move in the constructor
Foo f3{std::move(some_object)}; // move the object, followed by a move in the constructor
Run Code Online (Sandbox Code Playgroud)
我相信你已经知道(非)const-references的语义,所以我不会说明这一点.如果您需要我添加更多关于此的解释,请询问并且我将更新.
归档时间: |
|
查看次数: |
45567 次 |
最近记录: |