2013-04-09 5 views
5

Mam tę całkiem prostą funkcję, mam pewne wartości, które należy obliczyć, ale tylko jeden raz i najlepszy czas byłby w czasie kompilacji. Te wartości mają znaczenie tylko w ramach tej funkcji. Czy to jest dobre wykorzystanie constexpr czy powinienem zadeklarować je jako statyczną const?Czy powinienem używać takiego constexpr?

ps Wiem, że różnica w wydajności jest tak mała, że ​​nie ma znaczenia, ale chcę zrobić to w "prawidłowy" sposób C++ 11.

void MainWindow::UpdateDateTimes() 
{ 
// for some dumb reason DateTime only has add seconds method 
    // so we have to calculate the seconds per hour and the number of hours 
    // we do this with static constant values so that the calculations 
    // only happen once. 
    static constexpr const int secsPerHour = 60 * 60; 
    static constexpr const int cdtOffsetHours = -5; 
    static constexpr const int edtOffsetHours = -4; 
    static constexpr const int cetOffsetHours = 2; 
    static constexpr const int cdtOffsetSecs = secsPerHour * cdtOffsetHours; 
    static constexpr const int edtOffsetSecs = secsPerHour * edtOffsetHours; 
    static constexpr const int cetOffsetSecs = secsPerHour * cetOffsetHours; 

    QDateTime time(QDateTime::currentDateTimeUtc()); 

    ui->mTimeLocal->setDateTime(time.toLocalTime()); 

    ui->mTimeCDT->setDateTime(time.addSecs(cdtOffsetSecs)); 
    ui->mTimeEDT->setDateTime(time.addSecs(edtOffsetSecs)); 
    ui->mTimeCET->setDateTime(time.addSecs(cetOffsetSecs)); 
} 
+0

'constexpr' oznacza" const ". – Xeo

+1

'const int' jest wystarczające dla każdego, ale' constexpr int' może być bardziej jednoznaczne. Proszę nie mieszać dwóch. – ipc

+0

Czy za każdym razem, gdy funkcja jest wywoływana, nie jest tworzona i niszczona stała, i dlatego też należy dokonać obliczeń? Wiem, że można go zoptymalizować, ale chcę to naprawić, aby kod dokładnie wskazywał na to, co sugeruję. – EddieV223

Odpowiedz

7

Twoje użycie jest w porządku, jeśli nie trochę gadatliwe. W tym kontekście constexpr i const oznaczają dokładnie to samo. Może to zrobić jeden (lub nawet oba).

Fwiw, std::chrono::hours::period::num byłby inny sposób określenia 60*60 (jeśli chcesz pokazać trochę C++ 11 cred :-)).

Albo rzeczywiście można po prostu zrobić:

void MainWindow::UpdateDateTimes() 
{ 
    constexpr std::chrono::seconds cdtOffsetSecs = std::chrono::hours(-5); 
    constexpr std::chrono::seconds edtOffsetSecs = std::chrono::hours(-4); 
    constexpr std::chrono::seconds cetOffsetSecs = std::chrono::hours(2); 

    QDateTime time(QDateTime::currentDateTimeUtc()); 

    ui->mTimeLocal->setDateTime(time.toLocalTime()); 

    ui->mTimeCDT->setDateTime(time.addSecs(cdtOffsetSecs.count())); 
    ui->mTimeEDT->setDateTime(time.addSecs(edtOffsetSecs.count())); 
    ui->mTimeCET->setDateTime(time.addSecs(cetOffsetSecs.count())); 
} 

Również byłbym skłonny do upuść static. W moim systemie ten sam kod jest generowany z lub bez static. To wszystko dzieje się w czasie kompilacji, więc nie ma potrzeby "selekcji" inicjującej tylko raz "static".

Aktualizacja

Właśnie zrobić to krystalicznie czysta, ja edytowany oryginalny przykład do:

void f(int); 

void UpdateDateTimes() 
{ 
    constexpr std::chrono::seconds cdtOffsetSecs = std::chrono::hours(-5); 
    constexpr std::chrono::seconds edtOffsetSecs = std::chrono::hours(-4); 
    constexpr std::chrono::seconds cetOffsetSecs = std::chrono::hours(2); 

    f(cdtOffsetSecs.count()); 
} 

Opracowano go z -O1 (optymalizacje ledwo włączonych) z brzękiem ++ i libC++, a montaż jest :

.globl __Z15UpdateDateTimesv 
    .align 4, 0x90 
__Z15UpdateDateTimesv:     ## @_Z15UpdateDateTimesv 
    .cfi_startproc 
## BB#0: 
    pushq %rbp 
Ltmp2: 
    .cfi_def_cfa_offset 16 
Ltmp3: 
    .cfi_offset %rbp, -16 
    movq %rsp, %rbp 
Ltmp4: 
    .cfi_def_cfa_register %rbp 
    movl $-18000, %edi   ## imm = 0xFFFFFFFFFFFFB9B0 
    popq %rbp 
    jmp __Z1fi     ## TAILCALL 
    .cfi_endproc 

następnie opracowano program z tymi samymi ustawieniami:

void UpdateDateTimes2() 
{ 
    f(-18000); 
} 

a wygenerowany montaż jest:

.globl __Z16UpdateDateTimes2v 
    .align 4, 0x90 
__Z16UpdateDateTimes2v:     ## @_Z16UpdateDateTimes2v 
    .cfi_startproc 
## BB#0: 
    pushq %rbp 
Ltmp7: 
    .cfi_def_cfa_offset 16 
Ltmp8: 
    .cfi_offset %rbp, -16 
    movq %rsp, %rbp 
Ltmp9: 
    .cfi_def_cfa_register %rbp 
    movl $-18000, %edi   ## imm = 0xFFFFFFFFFFFFB9B0 
    popq %rbp 
    jmp __Z1fi     ## TAILCALL 
    .cfi_endproc 

Więc imho to jest tak blisko jak jeden kiedykolwiek dostanie się do free lunch. :-)