【问题标题】:Passing result of expression by reference通过引用传递表达式的结果
【发布时间】:2021-09-29 07:42:02
【问题描述】:

我有一个函数:

  int f(std::atomic<bool>& flag);

这需要检查flag 的值,这是一个被另一个线程更改的原子布尔值。如果我这样调用它,这个函数会按预期工作(f 看到另一个线程对标志所做的更改):

f(m_flag1);

我现在想要实现的目标稍微复杂一些,因为我不想将引用传递给单个原子 bool,而是传递给表达式,例如:

std::atomic<bool> x = m_flag1 && m_flag2;
f(x);

据我了解,直接将表达式传递给函数是错误的,因为这将是一个临时值,一旦调用函数就会被销毁。在我看来,r 值也不能作为参考传递。 不过,对x 的引用并没有多大帮助,因为我认为表达式只被评估一次,所以f 实际上并没有看到m_flag1 &amp;&amp; m_flag2

什么是获取表达式引用的简洁方法?我的其他线程应该持续评估x = m_flag1 &amp;&amp; m_flag2; 还是有更清洁的方法?

【问题讨论】:

  • 奇怪的是你必须传递表达式,(或接口错误)。
  • 请注意,您不能以原子方式同时使用两个原子变量。甚至 m_flag1 &amp;&amp; m_flag2 在不同的时间(原子地)读取两个标志的值。
  • What is a clean way to get a reference to an expression? 一个函数。
  • and passing that result 不,您必须重构您的函数f 以获取函数指针,或者充其量是提供基本operator ! &amp;&amp; bool etc. 布尔转换和一些运算符,然后在该对象内的那些运算符重载中实现您的逻辑。但我认为foo(std::function&lt;bool()&gt; flag) 然后foo([flag1, flag2](){ return flag1 &amp;&amp; flag2; }) 就足够了。
  • 请注意,a &amp;&amp; b 不是原子的,即使 ab 都是原子的。我认为你不能在这里避免显式同步。

标签: c++ reference rvalue


【解决方案1】:

来自问题cmets:

"[...]该函数需要检查一个布尔表达式[...]"

强调我的

如果您的函数不应该修改布尔标志而只评估其值,那么您可以将参数作为const 引用代替。

int f(const std::atomic<bool> & flag)
{
    // ...
}

电话可能是这样的:

int result = f(flag1 && flag2);

注意:如果您需要“同时”评估两个标志(很可能是这种情况),您需要添加一种同步机制,例如互斥锁,因为不管flag1flag2 是不是,表达式求值flag1 &amp;&amp; flag2 都不是原子的。


现在,如果您的函数可以修改标志,因此不可能将const 引用作为参考,那么您别无选择,只能将标志作为两个单独的参数和推迟函数内部的评估

再次来自问题cmets:

“问题是,通常只使用一个标志调用该函数,这是我需要两个标志的特殊情况”

考虑到这一点,你可以重载函数来处理带有一个或两个参数的情况,如下所示:

int f(std::atomic<bool> & flag)
{
    // ...
}
int f(std::atomic<bool> & flag1, std::atomic<bool> & flag2)
{
    auto expr_result = flag1 && flag2; // Evaluation of the expression deferred into the function
    // ...
}

如果您想让表达式的计算成为原子的,上述关于需要同步机制(例如互斥锁)的注释在这里仍然适用。

【讨论】:

    猜你喜欢
    • 2021-06-06
    • 1970-01-01
    • 2017-10-16
    • 2014-03-04
    • 2019-09-11
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 2019-11-12
    相关资源
    最近更新 更多