当前位置: 首页 > 知识库问答 >
问题:

我应该通过常量引用传递一个std::函数吗?

斜宁
2023-03-14

假设我有一个函数,它接受<code>std::function</code>:

void callFunction(std::function<void()> x)
{
    x();
}

我应该通过常量引用传递<code>x</code>吗

void callFunction(const std::function<void()>& x)
{
    x();
}

这个问题的答案是否会根据函数的作用而变化?例如,如果它是一个类成员函数或构造函数,它将 std::函数存储或初始化为成员变量。

共有3个答案

鱼阳伯
2023-03-14

与C 11中的惯例一样,按值/引用/const-reference传递取决于您如何处理参数。std::函数也不例外。

通过值传递允许您将参数移动到变量中(通常是类的成员变量):

struct Foo {
    Foo(Object o) : m_o(std::move(o)) {}

    Object m_o;
};

当您知道您的函数将移动它的参数时,这是最佳的解决方案,这样您的用户可以控制他们如何调用您的函数:

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

我相信您已经知道(非)const引用的语义,所以我不会详细阐述这一点。如果您需要我对此添加更多解释,请询问,我会更新。

佴博实
2023-03-14
匿名用户

如果您担心性能,并且没有定义虚拟成员函数,那么您很可能根本不应该使用std::function

使仿函数类型成为模板参数比< code>std::function允许更好的优化,包括内联仿函数逻辑。这些优化的效果很可能大大超过复制与间接有关如何传递< code>std::function的问题。

更快:

template<typename Functor>
void callFunction(Functor&& x)
{
    x();
}

汪信鸥
2023-03-14

如果您想要性能,则在存储时传递值。

假设您有一个名为“在 UI 线程中运行此”的函数。

std::future<void> run_in_ui_thread( std::function<void()> )

它在“ui”线程中运行一些代码,然后在完成时向<code>未来

我们正在考虑两个签名:

std::future<void> run_in_ui_thread( std::function<void()> ) // (A)
std::future<void> run_in_ui_thread( std::function<void()> const& ) // (B)

现在,我们可能会按如下方式使用这些:

run_in_ui_thread( [=]{
  // code goes here
} ).wait();

这将创建一个匿名闭包(一个lambda),用它构造一个< code>std::function,将它传递给< code>run_in_ui_thread函数,然后等待它在主线程中运行完毕。

在情况(A)中,< code>std::function直接从我们的lambda构造,然后在< code>run_in_ui_thread中使用。lambda被< code>move到< code>std::function中,因此任何可移动的状态都被有效地带入其中。

在第二种情况下,创建了一个临时的<code>std::函数,lambda是<code>将

到目前为止,一切顺利——他们两个的表现完全相同。除了< code>run_in_ui_thread将复制其函数参数以发送给ui线程执行!(它会在完成之前返回,所以它不能只使用对它的引用)。对于情况(A),我们简单地将< code>std::function移动到它的长期存储中。在情况(B)中,我们被迫复制< code>std::function。

该存储使传递值更为优化。如果有可能存储<code>std::函数移动将与常量一样有效

现在,如果我们在< code>std::function中有持久状态,这两者之间还有一些其他的差异。

假设<code>std::函数

std::f

这是一个相对奇怪的角落案例。

你想像对待任何其他可能重量级的、廉价的可移动类型一样对待std::函数。搬家很便宜,复制可能很昂贵。

 类似资料:
  • 如果我将一个变量传递给一个函数,但将该变量标记为常量,它会自动通过引用传递吗? 测试后:没有,因为它打印不同的内存位置。 没有权利?因为我只能传递一个指向内存位置的指针,而不是真正通过引用。如下所示:在C中通过引用传递 这几乎就是我所做的Java和C#编译器在幕后所做的事情。

  • 问题内容: 有任何想法吗?2天后仍然卡住。 问题答案: 将的结果分配给变量,然后将该变量传递给: 问题是,这需要引用,因为它修改了数组的内部表示(即,它使 当前元素指针 指向最后一个元素)。 的结果不能转换为参考。这是PHP语言的一种限制,出于简化的原因可能存在。

  • 有一组好的规则来确定是按值传递还是常量引用 如果函数打算将参数更改为副作用,则通过non-const引用。 如果函数不修改它的参数,并且参数是基元类型,则按值取它。 否则通过const引用获取它,除非在以下情况下:如果函数需要复制const引用,则按值获取它。 对于以下构造函数,如何确定它?

  • 严格的标准:在/var/www/parser/parser.php第130行中,只有变量应该通过引用传递 警告:mysqli_stmt::bind_param():第130行/var/www/parser/parser.php中准备好的语句中的变量数与参数数不匹配 严格的标准:在/var/www/parser/parser.php第131行中,只有变量应该通过引用传递 严格的标准:在/var/ww

  • 问题内容: 我正在使用SWIG从Java访问C ++代码。 公开非常量引用传递的std :: string参数的最简单方法是什么? 我有参考暴露为Java数组传递原语,感谢typemaps.i,和s ^暴露,感谢std_string.i。但是非const std :: string&被公开为不透明指针类型。 当前: 期望的: 更新 :我找到 了 解决方案,如下所述。但是,它花费了超过几秒钟的时间。

  • 所以,我试图用discord js和sqlite3做一件事,但在过去的几个小时里,我一直在讨论这个问题,我仍然不知道如何解决它。 因此,我试图获取仅在中可用的数据,但我不知道如何将其传递出去,以便返回预期值。我已经尝试过使用全局变量,把它放在更大的范围内,但我仍然不知道如何做到这一点。 对不起,如果我弄糊涂了,我不习惯一直问问题。 编辑:应该说我正在使用NPMSqlite3模块。https://w