Я рассказываю здесь длинную историю, потому что, в дополнение к прямому ответу, я хотел бы знать, были ли мои рассуждения, которые привели к этой ситуации, правильными.
У меня есть функция, принимающая 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 (предположительно) имеет указатель на свои данные, поэтому затем используем db
в foo
будет проходить через два уровня косвенности, которая кажется глупой. Очевидно, что лучшим способом было бы скопировать указатель на данные в 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 (временно истекающее), не так ли?
dynamic_bitset& set();
set()
возвращает lvalue.
В общем случае, если функция возвращает значение или ссылку на rvalue:
dynamic_bitset set();
dynamic_bitset&& set();
тогда выражение set()
является rvalue (в первом случае prvalue, а во втором xvalue). Однако, потому что в реальном коде set()
возвращает ссылку на lvalue, выражение set()
это значение.
значения категорий http://downloads.sehe.nl/stackoverflow/value-categories.svg
Других решений пока нет …