2014-09-12 2 views
3

В C структуры часто передаются указателями, чтобы предотвратить копирование данных на много.Есть ли разница в скорости передачи указателя или const struct

Интересно, правда, действительно ли это имеет значение? Не компиляторы предотвращают ненужные копии?

Например, если я отмечаю переменную const, будет ли компилятор оптимизировать копию?

Пример

struct my_t { 
    int a; 
    int b[24]; 
} 

int generate_updated_myt(const my_t c) { 
    // do something with c 
    return 0; 
} 

int generate_updated_myt(const my_t * c) { 
    // do something with *c 
    return 0; 
} 

Будет ли, в общем, будет ли разница в скорости между этими двумя?

+6

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

+1

@Peter Smit - Проверьте следующие ссылки и проверьте, отвечает ли он , ваш вопрос - Ссылка 1 - http://stackoverflow.com/questions/212237/constants-and-compiler-optimization-in-c Ссылка 2 - http://stackoverflow.com/questions/6313730/does-const-correctness-give-the-compiler-more-room-for-optimization –

+0

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

ответ

3

Если я правильно понял вопрос правильно, вы спрашиваете, может ли компилятор оптимизировать

int generate_updated_myt(const my_t c); 

такие, что вызовы generate_updated_myt() фактически передать указатель вместо фактической копии объекта (т. е. он может действовать аналогично C++ const&).

Рассмотрим следующий надуманный пример, если доступ к локальной копии c были реализованы в виде ссылки на объект передается в вместо как фактической копии:

#include <stdio.h> 

struct my_t { 
    int a; 
    int b[24]; 
}; 

int foo(void); 
int generate_updated_myt(const struct my_t c) 
{ 
    int a = c.a; 

    foo(); // if c is really a 'pointer' to the passed in object, 
      //  then this call to `foo()` may change the object 
      //  c refers to. 

    if (a != c.a) { 
     puts("how did my private copy of `c.a` get changed?"); 
    } 

    return a; 
} 

struct my_t g_instance; 

int main(void) 
{ 
    generate_updated_myt(g_instance); 
    return 0; 
} 

int foo(void) 
{ 
    int counter = g_instance.a++; 

    return counter; 
} 

Это одна из причин оптимизации вы предлагаете является не допускается.

И это даже не учитывает, что const очень легко отбрасывается (даже если это может быть плохая форма).

1

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

Единственное большое различие, которое я могу придумать, что я столкнулся с таким конструктивным решением, состоит в том, что если сгенерированный_updated_myt содержит какой-то возможноцилизируемый цикл, работающий на c, объявить его const, вероятно, недостаточно. Вы не могли бы получить векторизованную выход, если это не декларируется что-то вроде const my_t * restrict c __attribute__((aligned(64)))

Смежные вопросы