в то время как (1) По сравнению с для (;;) существует ли различие в скорости?

Вы должны взглянуть на рекомендованный ContactsContract.PhoneLookup провайдера

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

Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,...

152
задан hippietrail 16 October 2012 в 12:00
поделиться

14 ответов

В Perl они приводят к одним и тем же кодам операций:

$ perl -MO=Concise -e 'for(;;) { print "foo\n" }'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v ->3
9     <2> leaveloop vK/2 ->a
3        <{> enterloop(next->8 last->9 redo->4) v ->4
-        <@> lineseq vK ->9
4           <;> nextstate(main 1 -e:1) v ->5
7           <@> print vK ->8
5              <0> pushmark s ->6
6              <$> const[PV "foo\n"] s ->7
8           <0> unstack v ->4
-e syntax OK

$ perl -MO=Concise -e 'while(1) { print "foo\n" }'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v ->3
9     <2> leaveloop vK/2 ->a
3        <{> enterloop(next->8 last->9 redo->4) v ->4
-        <@> lineseq vK ->9
4           <;> nextstate(main 1 -e:1) v ->5
7           <@> print vK ->8
5              <0> pushmark s ->6
6              <$> const[PV "foo\n"] s ->7
8           <0> unstack v ->4
-e syntax OK

Аналогично в GCC:

#include <stdio.h>

void t_while() {
    while(1)
        printf("foo\n");
}

void t_for() {
    for(;;)
        printf("foo\n");
}

    .file   "test.c"
    .section    .rodata
.LC0:
    .string "foo"
    .text
.globl t_while
    .type   t_while, @function
t_while:
.LFB2:
    pushq   %rbp
.LCFI0:
    movq    %rsp, %rbp
.LCFI1:
.L2:
    movl    $.LC0, %edi
    call    puts
    jmp .L2
.LFE2:
    .size   t_while, .-t_while
.globl t_for
    .type   t_for, @function
t_for:
.LFB3:
    pushq   %rbp
.LCFI2:
    movq    %rsp, %rbp
.LCFI3:
.L5:
    movl    $.LC0, %edi
    call    puts
    jmp .L5
.LFE3:
    .size   t_for, .-t_for
    .section    .eh_frame,"a",@progbits
.Lframe1:
    .long   .LECIE1-.LSCIE1
.LSCIE1:
    .long   0x0
    .byte   0x1
    .string "zR"
    .uleb128 0x1
    .sleb128 -8
    .byte   0x10
    .uleb128 0x1
    .byte   0x3
    .byte   0xc
    .uleb128 0x7
    .uleb128 0x8
    .byte   0x90
    .uleb128 0x1
    .align 8
.LECIE1:
.LSFDE1:
    .long   .LEFDE1-.LASFDE1
.LASFDE1:
    .long   .LASFDE1-.Lframe1
    .long   .LFB2
    .long   .LFE2-.LFB2
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI0-.LFB2
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI1-.LCFI0
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE1:
.LSFDE3:
    .long   .LEFDE3-.LASFDE3
.LASFDE3:
    .long   .LASFDE3-.Lframe1
    .long   .LFB3
    .long   .LFE3-.LFB3
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI2-.LFB3
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI3-.LCFI2
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE3:
    .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section    .note.GNU-stack,"",@progbits

Итак, я думаю, ответ таков: они одинаковы во многих компиляторах. Конечно, для некоторых других компиляторов это не обязательно так, но есть вероятность, что код внутри цикла в любом случае будет в несколько тысяч раз дороже, чем сам цикл, так что кого это волнует?

216
ответ дан 23 November 2019 в 22:07
поделиться

Я бы подумал, что оба они одинаковы по производительности. Но я бы предпочел while (1) для удобства чтения, но я сомневаюсь, зачем вам бесконечный цикл.

-3
ответ дан 23 November 2019 в 22:07
поделиться

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


Моя точка зрения, которая подразумевалась, но не выражалась явно выше, заключается в том, что достойный компилятор будет генерировать один и тот же код для обеих форм цикла. Важнее то, что конструкция цикла является второстепенной частью времени выполнения любого алгоритма, и вы должны сначала убедиться, что вы оптимизировали алгоритм и все остальное, что с ним связано. Оптимизация конструкции цикла должна быть в самом низу списка приоритетов.
-15
ответ дан 23 November 2019 в 22:07
поделиться

в то время как (1) - это идиома для для (;;) , которая распознается большинством компиляторов.

Я был рад увидеть, что perl распознает С до (0) тоже.

2
ответ дан 23 November 2019 в 22:07
поделиться

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

5
ответ дан 23 November 2019 в 22:07
поделиться

Для всех людей, которые утверждают, что вы не должны использовать неопределенные циклы while, и предлагают глупые вещи, такие как использование open goto (серьезно, ой)

while (1) {
     last if( condition1 );
     code();
     more_code(); 
     last if( condition2 ); 
     even_more_code(); 
}

Can ' На самом деле это может быть эффективно представлено любым другим способом. Не обошлось и без создания переменной выхода и использования черной магии для ее синхронизации.

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

flow: { 

   if ( condition ){ 
      redo flow;
   }
   if ( othercondition ){ 
       redo flow;
   }
   if ( earlyexit ){ 
       last flow;
   }
   something(); # doesn't execute when earlyexit is true 
}

В конечном итоге скорость не так важна.

Беспокойство о том, насколько эффективны с точки зрения скорости различные циклические конструкции, - огромная трата времени. Преждевременная оптимизация насквозь. Я не могу вспомнить ни одной ситуации, которую я когда-либо видел, когда код профилирования обнаруживал узкие места в моем выборе конструкции цикла.

Обычно это how цикла и what цикла.

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

Если вы используете уловку "goto LABEL", о которой упоминал кто-то, и я должен использовать ваш код, будьте готовы спать с одним открытым глазом, особенно если вы делаете это более одного раза, потому что такого рода вещи создают ужасающе спагетти-код.

Тот факт, что вы можете создать код спагетти, не означает, что вы должны

13
ответ дан 23 November 2019 в 22:07
поделиться

for (;;) - это на один символ меньше для ввода, если вы хотите пойти в этом направлении для оптимизации.

26
ответ дан 23 November 2019 в 22:07
поделиться

There is no difference according to the standard. 6.5.3/1 has:

The for statement

for ( for-init-statement ; conditionopt ; expressionopt ) statement

is equivalent to

{
  for-init-statement
  while ( condition ) {
    statement
    expression ;
  }
}

And 6.5.3/2 has:

Either or both of the condition and the expression can be omitted. A missing condition makes the implied while clause equivalent to while(true).

So according to the C++ standard the code:

for (;;);

is exactly the same as:

{
  while (true) {
    ;
    ;
  }
}
31
ответ дан 23 November 2019 в 22:07
поделиться

Компилятор Visual C ++, используемый для выдачи предупреждения для

while (1) 

(постоянное выражение), но не для

for (;;)

. Я продолжил практику, предпочитая для ( ;;) по этой причине, но я не знаю, продолжает ли компилятор это делать в наши дни.

28
ответ дан 23 November 2019 в 22:07
поделиться

Нет особых причин предпочитать одно другому. Я действительно думаю, что while (1) и особенно while (true) более читабельны, чем для (;;) , но это только мое предпочтение.

53
ответ дан 23 November 2019 в 22:07
поделиться

Используя GCC, кажется, что они оба компилируются на один и тот же язык ассемблера:

L2:
        jmp     L2
55
ответ дан 23 November 2019 в 22:07
поделиться

Другим решением было бы отделение кода от макетов с помощью соответствующего механизма создания шаблонов.

-121--2478554-

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

-121--1918258-

От Stroustup, TC++ PL (3-е издание), § 6,1,1:

Любопытное обозначение для (;;) является стандартным способом задания бесконечного цикла; ты можешь произнести это «навсегда.» [...] , в то время как (true) является альтернативой.

Я предпочитаю для (;) .

9
ответ дан 23 November 2019 в 22:07
поделиться

Теоретически полностью наивный компилятор мог бы сохранить литерал '1' в двоичном файле (тратя пространство) и проверить, не 1 == 0 на каждой итерации (тратя время и больше места).

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

2
ответ дан 23 November 2019 в 22:07
поделиться

Я удивлен, что никто не предложил более прямую форму, соответствующую желаемой сборке:

forever:
     do stuff;
     goto forever;
2
ответ дан 23 November 2019 в 22:07
поделиться
Другие вопросы по тегам:

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