2015-05-04 2 views
45

Некоторые люди не знают, что это possible to pass and return structs by value in C. Мой вопрос в том, что компилятор делает ненужные копии при возврате структур в компиляторах C. Do C, таких как GCC, использует оптимизацию Return value optimization(RVO) или это только концепция C++? Все, что я прочитал о RVO и копировании elision, относится к C++.Оптимизация возвращаемого значения и копирование в C

Рассмотрим пример. В настоящее время я внедряю double-double data type в C (или, скорее, float-float для начала, потому что я нахожу это легко для модульного теста). Рассмотрим следующий код.

typedef struct { 
    float hi; 
    float lo; 
} doublefloat; 

doublefloat quick_two_sum(float a, float b) { 
    float s = a + b; 
    float e = b - (s - a); 
    return (doublefloat){s, e}; 
} 

Будет ли компилятор сделать временную копию значения doublefloat я вернуть или может временная копия быть опущены?

Что такое оптимизация значений имен (NRVO) в C? У меня есть другая функция

doublefloat df64_add(doublefloat a, doublefloat b) { 
    doublefloat s, t; 
    s = two_sum(a.hi, b.hi); 
    t = two_sum(a.lo, b.lo); 
    s.lo += t.hi; 
    s = quick_two_sum(s.hi, s.lo); 
    s.lo += t.lo; 
    s = quick_two_sum(s.hi, s.lo); 
    return s; 
} 

В этом случае я возвращаю названную структуру. Может ли временная копия в этом случае быть отменена?

Следует отметить, что это общий вопрос для C и что примеры кода, которые я использовал здесь, являются только примерами (когда я оптимизирую это, я буду использовать SIMD с intrinsics в любом случае). Я знаю, что я мог бы посмотреть на сборку, чтобы увидеть, что делает компилятор, но я думаю, что это интересный вопрос.

+3

@BaummitAugen, я тоже не был уверен, следует ли использовать тег C++. Но я думаю, что я ясно дал понять в своем вопросе, что речь идет о C. Я надеялся, что тег C++ привлечет людей, которые являются экспертами на обоих языках. –

+0

@BaummitAugen есть такая концепция в C вообще. Я удалил тег 'C', поскольку он кажется мне лишним. –

+0

@IvayloStrandjev все еще вопрос о C, тег относится к вопросу, нет? – BeyelerStudios

ответ

35

РВО/NRVO явно разрешены по правилу «как если бы» в С.

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

Не перегружая их, вы не получаете видимых побочных эффектов от копирования, а потому ничего не прекращаете компилятору.

+4

Адрес переменной в функции и адрес переменной, назначенной внешнему, может быть идентичным, поскольку у них есть неперекрывающиеся времена жизни: временный мост не может иметь свой адрес, и он не может использовать адрес другой двух переменных обнаружено. Это, я думаю, не позволяет обнаружить, что это произошло (теоретически) по стандарту: на практике, если переменная в функции и переменная, назначенная снаружи, имеют один и тот же адрес, вероятность того, что вы являетесь свидетелем NRVO. – Yakk

+1

Проверяя это на gcc, g ++, clang, clang ++, выясняется, что каждый делает NRVO правильно, кроме gcc '-xc', который генерирует лишние копии, когда у вас есть:' struct s f() {struct s x = g(); return x; } ' – Peaker

31

Причина, по которой это связано с C++, заключается в том, что в C++ RVO имеет побочные эффекты (т. Е. Не вызывает деструктор временных объектов, а также конструктор копирования или оператор присваивания результирующих объектов).

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

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

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