Параллельное присваивание в C ++ - PullRequest
6 голосов
/ 08 ноября 2008

Есть ли способ сделать параллельное назначение в C ++? В настоящее время ниже компилируется (с предупреждениями)

#include <iostream> 

int main() { 
  int a = 4;
  int b = 5;
  a, b = b, a;
  std::cout << "a: " << a << endl
            << "b: " << b << endl;

  return 0;
}

и отпечатки:

a: 4
b: 5

То, что я хотел бы напечатать ... если бы это не было очевидно, это:

a: 5
b: 4

Как, скажем, в ruby ​​или python.

Ответы [ 6 ]

16 голосов
/ 08 ноября 2008

Это невозможно. Пример вашего кода

a, b = b, a;

интерпретируется следующим образом:

a, (b = b), a

Это ничего не делает. Оператор запятой заставляет его возвращать значение a (самый правый операнд). Поскольку назначение связывает крепче, b = b в скобках.

Правильный способ сделать это просто

std::swap(a, b);

Boost включает в себя класс кортежа, с которым вы можете

tie(a, b) = make_tuple(b, a);

Он внутренне создает кортеж ссылок на a и b, а затем присваивает им кортеж b и a.

3 голосов
/ 08 ноября 2008

Параллельное присваивание не поддерживается в C ++. Языки, которые поддерживают это, обычно обрабатывают a,b,c как список по обе стороны от оператора присваивания, это не тот способ, которым оператор запятой работает в C ++. В C ++ a, b оценивает a, а затем b, поэтому a, b = b, a совпадает с a; b = b; a;.

1 голос
/ 08 ноября 2008

Или Perl. Но нет, это не возможно (насколько я знаю), вам нужно использовать временную переменную, как в:

int a = 4;
int b = 5;

{
    int tmp = a;
    a = b;
    b = tmp;
}

К вашему сведению, внутренне эти языки (или, по крайней мере, Perl) создают временный список { a, b }, затем присваивают список двум переменным. Другими словами, это по крайней мере как исполнитель, если только немного более грязный.

0 голосов
/ 21 декабря 2017

Этот вопрос очень старый & ndash; Я только что наткнулся на это сегодня ...
... и удивлялся, почему никто не дал такой ответ раньше ...

Я думаю, это возможно сделать в C ++ 11 подобно тому, как это делает Python (под капотом):

#include <iostream>
using namespace std;

int main()
{
  int a = 4, b = 5;
  cout << "Before assignment: a: " << a << ", b: " << b << endl;
  pair<int&, int&> ba(b, a);
  ba = make_pair(a, b); // <===: (b, a) = (a, b)
  cout << "After assignment : a: " << a << ", b: " << b << endl;
  return 0;
}

Я пробовал это на ideone.com . Выход был:

Before assignment: a: 4, b: 5
After assignment : a: 5, b: 4

Если я правильно помню (я не эксперт по Python), в Python a, b обозначает пару. ( Python Doc .: 5.3. Кортежи и последовательности )

Такую пару можно легко сделать в C ++ 11, например. с std::pair. В этом случае я сделал пару ссылок и назначил пару значений. Он работает, когда make_pair() загружает обе переменные до того, как правая пара (значений) будет присвоена левой паре ссылок.

Снова прокручивая, я понимаю, что этот ответ близок к основанному на ускорении решению Йоханнесу .

Может быть, причина в том, что он не работал в C ++ 03. Я попытался в coliru.stacked-crooked.com: с -std=c++03 ужасно читать ошибки компилятора & ndash; меняется на -std=c++11, и он прекрасно компилируется и выполняется, как описано выше.

Отказ

Я просто не могу себе представить, для чего это решение хорошо, и какую практическую ценность оно может иметь. Это не то, что я пытался сделать. Как и во многих других ответах, говорится: «Это не работает». ИМХО, это так (написание это правильно в соответствии с языком C ++) ...

0 голосов
/ 10 ноября 2008

В стандартной библиотеке такой функции нет. Вы можете написать набор шаблонных функций:

template <typename T1> void ParAssign(T1& Lhs_1, T1 const& Rhs1);
template <typename T1, typename T2> void ParAssign(T1& Lhs1, T2& Lhs2, T1 const& Rhs1, T2 const& Rhs2);
// etc.
ParAssign(a,b,
          b,a);

Это не тривиально, если есть псевдонимы, как в вашем примере подкачки.

0 голосов
/ 08 ноября 2008

Или Луа ...
Есть приемы с C / C ++, такие как использование xor или операций, но с риском переполнения и тому подобное. Просто сделай это больно, с тремя заданиями. Ничего страшного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...