С ++ назначение - стильно или перформанс? - PullRequest
11 голосов
/ 19 мая 2010

Писая код Java много лет, я был поражен, увидев следующее утверждение C ++:

int a,b;
int c = (a=1, b=a+2, b*3);

Мой вопрос: это выбор стиля кодирования или он приносит реальную выгоду? (Я ищу практический вариант использования)

Я думаю, что компилятор увидит его так же, как показано ниже:

int a=1, b=a+2;
int c = b*3;

(Какое официальное название для этого? Я предполагаю, что это стандартный синтаксис C / C ++.)

Ответы [ 9 ]

17 голосов
/ 19 мая 2010

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

9 голосов
/ 19 мая 2010

Похоже на неясное использование оператора (запятая).

Это не репрезентативный способ работы в C ++.

6 голосов
/ 20 мая 2010

Единственным «хорошим стилем» использования для оператора запятой может быть оператор for, который имеет несколько переменных цикла, используется что-то вроде этого:

// Copy from source buffer to destination buffer until we see a zero
for (char *src = source, *dst = dest; *src != 0; ++src, ++dst) {
    *dst = *src;
}

Я поставил «хороший стиль» в кавычках, потому что почти всегда есть лучший способ, чем использовать запятую.

Другой контекст, в котором я видел это, используется с троичным оператором, когда вы хотите иметь несколько побочных эффектов, например,

bool didStuff = DoWeNeedToDoStuff() ? (Foo(), Bar(), Baz(), true) : false;

Опять же, есть лучшие способы выразить подобные вещи. Эти идиомы являются пережитками тех дней, когда мы могли видеть только 24 строки текста на наших мониторах, и втискивание большого количества материала в каждую строку имело некоторое практическое значение.

3 голосов
/ 19 мая 2010

Не знаю его названия, но оно, похоже, отсутствует в Руководстве по кодированию безопасности заданий !

Серьезно: C ++ позволяет вам делать много вещей во многих контекстах, даже если они не обязательно звучат. С большой силой приходит большая ответственность ...

2 голосов
/ 20 мая 2010

В вашем примере кода используются две не очень известные новичкам (но не особо скрытые) функции выражений C:

  • оператор запятой: обычный бинарный оператор, роль которого состоит в возвращении последнего из двух его операндов. Если операнды являются выражением, они оцениваются слева направо.
  • присваивание в качестве оператора, возвращающего значение. Назначение Си не является оператором, как в других языках, и возвращает присвоенное значение.

В большинстве случаев использования обеих этих функций используется некоторая форма запутывания. Но есть некоторые законные. Дело в том, что вы можете использовать их везде, где можете предоставить выражение: внутри условного оператора if или while, в блоке итерации цикла for, в параметрах вызова функции (при использовании комы необходимо использовать скобки, чтобы не перепутать с фактическими параметрами функции) , в параметре макроса и т. д.

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

Например, обратная функция может быть написана, как показано ниже, благодаря оператору запятой:

void reverse(int * d, int len){
    int i, j;

    for (i = 0, j = len - 1 ; i < j ; i++, j--){
       SWAP(d[i], d[j]);
    }
}

Другое законное (на самом деле не запутанное) использование оператора комы, которое я имею в виду, - это макрос DEBUG, который я нашел в каком-то проекте, определенном как:

#ifdef defined(DEBUGMODE)
#define DEBUG(x) printf x
#else
#define DEBUG(x) x
#endif

Вы используете это как:

DEBUG(("my debug message with some value=%d\n", d));

Если DEBUGMODE включен, то вы получите printf, если не вызывать функцию-обертку, но выражение между круглыми скобками все еще допустимо C. Дело в том, что любой побочный эффект при печати кода будет применяться как в коде выпуска и отладочный код, подобный представленному:

DEBUG(("my debug message with some value=%d\n", d++));

С указанным выше макросом d всегда будет увеличиваться независимо от режима отладки или выпуска.

Вероятно, есть и другие редкие случаи, когда значения запятой и присваивания полезны, и код легче писать, когда вы их используете.

Я согласен, что оператор присваивания является отличным источником ошибок, поскольку его легко спутать с условием == в условном выражении.

Я согласен, что, поскольку запятая также используется с другим значением в других контекстах (вызовы функций, списки инициализации, списки объявлений), это был не очень хороший выбор для оператора. Но в принципе это не хуже, чем использование <и> для параметров шаблона в C ++, и существует в C с гораздо более старых дней.

2 голосов
/ 19 мая 2010

Это называется «запутанный C». Это законно, но предназначено, чтобы запутать читателя. И, похоже, сработало. Если вы не пытаетесь быть неясным, лучше избегать этого.

Хоти

1 голос
/ 20 мая 2010

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

Это и выбор стиля кодирования, и он имеет реальную выгоду.

Это явно другой стиль кодирования по сравнению с вашим эквивалентным примером.

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

Вариант использования: Боб приходит ко мне с кодом, содержащим эту строку. Я перевел его на маркетинг.

1 голос
/ 19 мая 2010

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

int a=1; 
int b=3;
int c=9;

Математика даже не будет выполняться во время выполнения во время выполнения. (а некоторые из переменных могут быть даже полностью исключены).

Что касается выбора стиля кодирования, я предпочитаю второй пример. В большинстве случаев меньше вложений лучше, и вам не понадобятся лишние скобки. Поскольку использование представленных запятых будет известно практически всем программистам C ++, у вас есть выбор стиля. В противном случае, я бы сказал, поместите каждое назначение в отдельной строке.

0 голосов
/ 20 мая 2010

Вы обнаружили отвратительное злоупотребление оператором запятой , написанное программистом, который, вероятно, желает, чтобы C ++ имел множественные назначения. Это не так. Мне вспомнили старую пилу, на которой можно писать фортран на любом языке. Очевидно, вы можете попытаться написать язык защищенных команд Дейкстры на C ++.

Чтобы ответить на ваш вопрос, это просто вопрос (плохого) стиля, и компилятору все равно - компилятор сгенерирует точно такой же код, как и то, что программист C ++ считает разумным и разумным.

Вы можете убедиться в этом сами, если сделаете две маленькие примерные функции и скомпилируете обе с опцией -S.

...