Как узнать, будет ли перемещен объект, переданный как r-значение? - PullRequest
0 голосов
/ 05 ноября 2018

Я передаю лямбду в функцию, которая принимает ее как ссылку на r-значение.

Если моя лямбда определена в самом вызове функции, мне все равно, что будет с ней позже.
Но если моя лямбда-переменная (скажем, я хочу использовать ее более одного раза), я хочу знать, что она не перемещена из.

Есть ли способ узнать, будет ли он перемещен или нет, что сделает его непригодным для использования или пригодным для использования соответственно после возврата вызова?

EDIT:

Просто чтобы прояснить, лямбда ничего не захватывает. Меня волнует сам функтор: auto fn = [](int a){ return a; };

Позвольте мне сделать это еще сложнее. Я передам функтор как значение: std::move(fn)

std :: move - это только приведение. Он ничего не перемещает, но аргумент rvalue в вызываемом объекте теперь привязывается к правильному rvalue.

Вопрос в том, гарантированно ли будет перемещен fn? Это гарантированно не будет перемещено? Есть ли вообще гарантия? Могу ли я заставить его вести себя так или иначе, или это до вызываемого абонента?

Я хочу знать, потому что я хочу знать, могу ли я передать fn в качестве параметра функции дважды.

РЕДАКТИРОВАТЬ # 2:

Давайте рассмотрим другой случай. Я должен вызвать функцию с контейнером. Вектор, карта или что-то еще. Подпись функции говорит &&. Я могу обернуть свой контейнер с помощью STD Move или STD вперёд, чтобы получить rvalue ref для вызываемого. Это на самом деле одно и то же, так как они оба просто прославленные актеры.

Теперь, допустим, я использовал std forward, потому что мне действительно нравится, когда мой контейнер никуда не уходит.

Я легко вижу, что вызываемый абонент не знает о своем намерении, и перемещаю свой контейнер, делая его недействительным (распотрошенным) после вызова. Это дефект языка или я что-то упустил?

1 Ответ

0 голосов
/ 05 ноября 2018

Что ж, если функция принимает универсальную ссылку, и вы хотите запретить перемещение, есть много вариантов для выбора, среди прочего:

  1. Передача по постоянной ссылке (C ++ 17 имеет std::as_const(), чтобы упростить это).
  2. Сохраните его как локальный и не конвертируйте в rvalue-reference. Кажется, ты это делаешь.
  3. Используйте что-то для явного преобразования rvalue-ссылки в lvalue-ссылку.

Конечно, если лямбда не захватывает местных жителей по значению, которые имеют различные вселения семантику, чем копировать семантики, и вызываемая функция на самом деле имеет преимущество, что точка является спорным.

Это действительно воспользуется возможностью?
Изучите договор, а затем просто доверьтесь ему или попробуйте проверить выполнение. Там нет ярлыка.

Не будем даже упоминать, что C ++ позволяет программисту явно отказаться от (ограниченной) безопасности, которую он обеспечивает.

...