【问题标题】:Why do I need to call std::move on a temporary dynamic_bitset?为什么我需要在一个临时的 dynamic_bitset 上调用 std::move?
【发布时间】:2016-04-22 21:59:12
【问题描述】:

我在这里讲述的是一个冗长的背景故事,因为除了直接回答之外,我还想知道导致这种情况的推理是否正确。

我有一个函数采用dynamic_bitset<> 参数(来自Boost.dynamic_bitset)。 说它看起来像这样。

void foo(boost::dynamic_bitset<> db) {
    // do stuff
}

碰巧它只使用临时调用,从构造函数构建,如foo(boost::dynamic_bitset&lt;&gt;{5}.set())(使用设置了所有位的 5 位位集调用)。

我的位集只有少量位(少于 32 个)。所以一开始,我想“我只是按值传递它;副本比指针小。”但后来我想“它是动态的,所以它必须在堆上分配空间。我想避免不必要的分配和释放。”

所以,我可以做到

void foo(const boost::dynamic_bitset<>& db);

但是一个引用是一个指针,而一个dynamic_bitset(大概)有一个指向它的数据的指针,所以在foo 中使用db 会经历两层间接,这看起来很愚蠢。显然最好的方法是将指向数据的指针复制到foo,而不是重新分配和复制堆上的数据。

“啊哈!”我说。 “当然,这就是移动语义的用途。”所以,我把签名改成

void foo(boost::dynamic_bitset<>&& db);

然后,调用foo(boost::dynamic_bitset&lt;&gt;{5}.set()) 会产生编译器错误cannot bind 'boost::dynamic_bitset&lt;&gt;' lvalue to 'boost::dynamic_bitset&lt;&gt;&amp;&amp;'。 我必须改为打电话 foo(std::move(boost::dynamic_bitset&lt;&gt;{5}.set())) 然后一切正常。

为什么我需要调用 std::move? 这看起来显然是一个 xvalue(一个即将到期的临时值),不是吗?

【问题讨论】:

  • 这不取决于set 是什么吗?

标签: c++ move-semantics boost-dynamic-bitset xvalue


【解决方案1】:

来自the boost docs

dynamic_bitset& set();

set() 返回一个左值。

一般来说,如果函数按值返回,或者按右值引用返回:

dynamic_bitset   set();
dynamic_bitset&& set();

那么表达式set() 是一个右值(在第一种情况下是prvalue,在第二种情况下是xvalue)。但是因为在实际代码中set() 返回一个左值引用,所以表达式set() 是一个左值。

category values http://downloads.sehe.nl/stackoverflow/value-categories.svg

【讨论】:

  • 看,这让我很困惑,因为我认为没有分配给任何东西的函数调用的结果总是一个 xvalue。移动语义的典型示例似乎总是takemove( foo() ),其中没有讨论foo() 的返回类型:结果是一个没有名称的临时值,因此是一个xvalue。你是说这只有在foo() 不返回引用时才有效?
  • @Kundor:更新的答案希望澄清。
猜你喜欢
  • 2017-06-11
  • 2012-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-10
  • 2014-12-19
  • 2021-11-13
相关资源
最近更新 更多