4

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

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

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

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

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

所以,我可以做到

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

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

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

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

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

为什么我需要调用 std::move? 这似乎很明显是一个 xvalue(一个临时的即将到期),不是吗?

4

1 回答 1

5

来自boost 文档

dynamic_bitset& set();

set()返回一个左值。

通常,如果函数按值或右值引用返回:

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

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

类别值 http://downloads.sehe.nl/stackoverflow/value-categories.svg

于 2016-04-22T22:28:59.720 回答