2016-04-22 5 views
4

Я рассказываю здесь длинную предысторию, потому что, помимо прямого ответа, я хотел бы знать, правильны ли мои рассуждения, которые привели к этой ситуации.Зачем мне нужно вызвать std :: move на временном dynamic_bitset?

У меня есть функция, принимающая аргумент dynamic_bitset<> (от Boost.dynamic_bitset). Скажите, что это выглядит так.

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

Так получился, что это только когда-либо вызывается временными, построенным из конструктора, так как в foo(boost::dynamic_bitset<>{5}.set()) (звонить с 5-битным BitSet со всеми установленными битами).

Мои биты имеют только небольшое количество бит (менее 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 (временное истечение срока действия), не так ли?

+1

не зависит, что бы на то, что 'set' это? –

ответ

5

the boost docs От:

dynamic_bitset& set(); 

set() возвращает именующее выражение.

В общем случае, если функция возвращает по значению или по ссылке RValue:

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

то выражение set() является Rvalue (в первом случае prvalue, а во втором xvalue). Однако, поскольку в фактическом коде set() возвращает ссылку lvalue, выражение set() является значением lvalue.

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

+1

Видите ли, это меня смущает, потому что я думал, что результат вызова функции, который не назначен ни на что, всегда является значением xvalue. Канонический пример семантики перемещения всегда кажется «takemove (foo())», где не рассматривается тип возвращаемого значения 'foo()': результат является временным без имени, следовательно, значением xvalue. Вы говорите, что это работает только в том случае, если 'foo()' не возвращает ссылку? – Kundor

+0

@ Kundor: Обновленный ответ, надеюсь, уточнить. –