Передача ссылки rvalue в аргументе функции [duplicate]

ДА

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

Позвольте мне объяснить.


@ torsten-marek прав, что регулярное выражение не может проверять вложенные шаблоны, подобные этому, но возможно определить вложенный шаблон регулярного выражения, который позволит вам захватите вложенные структуры, подобные этому , до некоторой максимальной глубины . Я создал один, чтобы записать комментарии в формате EBNF ( попробуйте здесь ), например:

(* This is a comment (* this is nested inside (* another level! *) hey *) yo *)

Регулярное выражение (для комментариев с одной глубиной ) является следующим:

m{1} = \(+\*+(?:[^*(]|(?:\*+[^)*])|(?:\(+[^*(]))*\*+\)+

Это может быть легко адаптировано для ваших целей, заменив \(+\*+ и \*+\)+ на { и } и заменив все между простыми [^{}]:

p{1} = \{(?:[^{}])*\}

( Вот ссылка , чтобы попробовать это.)

Чтобы вложить, просто разрешите этот шаблон внутри самого блока:

p{2} = \{(?:(?:p{1})|(?:[^{}]))*\}
  ...or...
p{2} = \{(?:(?:\{(?:[^{}])*\})|(?:[^{}]))*\}

Чтобы найти тройные вложенные блоки, используйте:

p{3} = \{(?:(?:p{2})|(?:[^{}]))*\}
  ...or...
p{3} = \{(?:(?:\{(?:(?:\{(?:[^{}])*\})|(?:[^{}]))*\})|(?:[^{}]))*\}

Появился четкий шаблон. Чтобы найти комментарии, вложенные в глубину N, просто используйте регулярное выражение:

p{N} = \{(?:(?:p{N-1})|(?:[^{}]))*\}

  where N > 1 and
  p{1} = \{(?:[^{}])*\}

Сценарий можно записать для рекурсивного генерации этих регулярных выражений, но это выходит за рамки того, для чего мне это нужно. (Это остается как упражнение для читателя.

13
задан moswald 26 September 2012 в 17:47
поделиться

4 ответа

Я всегда помню lvalue как значение, которое имеет имя или может быть адресовано. Поскольку x имеет имя, оно передается как lvalue. Цель ссылки на rvalue - разрешить функции полностью clobber-значение любым способом, который он считает нужным. Если мы передадим x по ссылке, как в вашем примере, тогда у нас нет способа узнать, безопасно ли это сделать:

void foo(int &&) {}
void bar(int &&x) { 
    foo(x); 
    x.DoSomething();   // what could x be?
};

Выполнение foo(std::move(x)); явно сообщает компилятору, что вы сделали это с помощью x и больше не нуждается в этом. Без этого движения с существующим кодом могут случиться плохие вещи. std::move является защитой.

std::forward используется для идеальной пересылки в шаблонах.

8
ответ дан SaulBack 22 August 2018 в 01:29
поделиться
  • 1
    Мне нравятся ваши объяснения. «Говоря компилятору, что мы сделали», часть сделала кусочки лучше уложены в моей голове. – moswald 27 September 2012 в 00:06

Это правило no name ". Внутри bar, x имеет имя ... x. Так что теперь это lvalue. Передача чего-либо функции в качестве ссылки rvalue не делает ее rvalue внутри функции.

Если вы не видите, почему так должно быть, спросите себя: что x после foo возвращается? (Помните, что foo свободно перемещается x.)

9
ответ дан David Schwartz 22 August 2018 в 01:29
поделиться
  • 1
    Тип x по-прежнему является ссылкой rvalue, потому что это то, что объявлено как, но выражение является значением lvalue. Я бы просто изменил & quot; не делает его ссылкой rvalue & quot; to "не делает его rvalue". – Joseph Mansfield 26 September 2012 в 18:09
  • 2
    @sftrabbit: Спасибо. Так-то лучше. – David Schwartz 26 September 2012 в 18:11

Почему он трансформируется в int один раз внутри тела функции?

Это не так; это все еще ссылка на rvalue .

Когда в выражении появляется выражение, это lvalue - даже если это будет ссылка на rvalue . Он может быть преобразован в rvalue , если выражение требует, чтобы (то есть, если его значение необходимо); но он не может быть связан с ссылкой rvalue .

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

Кроме того, почему бы не std::move?

Почему бы и нет? Это будет иметь больше смысла, чем std::forward, который предназначен для шаблонов, которые не знают, является ли аргумент ссылкой.

10
ответ дан Mike Seymour 22 August 2018 в 01:29
поделиться

rvalue и lvalue являются категориями выражений.

rvalue reference и lvalue reference ] являются категориями ссылок.

Внутри декларации T x&& = <initializer expression> переменная x как тип T & amp; & amp ;, и она может быть привязана к выражению (the), которое является выражением rvalue . Таким образом, T & amp; & amp; был назван ссылочным типом rvalue , поскольку он ссылается на выражение rvalue .

Внутри декларации T x& = <initializer expression> переменная x как тип T & amp ; и он может быть связан с выражением (the), которое является выражением lvalue (++). Таким образом, T & amp; был назван ссылочным типом lvalue , поскольку он может ссылаться на выражение lvalue .

Важно, чтобы на C ++ было сделано различие между именования объекта, которое появляется внутри объявления, и когда это выражение появляется внутри выражения.

Когда имя появляется внутри выражения, как в foo(x), имя x само по себе является выражением , называемый id-выражением. По определению и id-выражение всегда является выражением lvalue , а выражения lvalue не могут быть связаны с ссылкой на rvalue .

0
ответ дан Oliv 22 August 2018 в 01:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: