2013-04-09 26 views
5

Bu oldukça basit bir işleve sahibim, hesaplanması gereken bazı değerlere sahibim ama sadece bir kez ve en iyi zaman derleme zamanında. Bu değerler sadece bu işlevde önemlidir. Bu, constexpr'in iyi bir kullanımı mıdır yoksa sadece static const mı yazmalıyım?Bu gibi constexpr kullanmalı mıyım?

ps Performans farkının çok önemli olmadığını biliyorum, ancak bunu "Doğru" C++ 11 yolu yapmak istiyorum.

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',' const' anlamına gelir. – Xeo

+1

'const int' her biri için yeterlidir, ancak' constexpr int' daha açık olabilir. Lütfen ikisini karıştırmayın. – ipc

+0

İşlev her çağrıldığında bir const int yaratılmamış ve yok edilmemiştir, bu nedenle hesaplamalar da yapılmalıdır? Bunun optimize edilebileceğini biliyorum, ancak doğru bir şekilde yapmak istiyorum, bu yüzden kod tam olarak ne ima ettiğimi söylüyor. – EddieV223

cevap

7
Kullanımınız gayet iyi değilse de iyidir. Bu bağlamda constexpr ve const tam olarak aynı şeyi ifade eder. Ya bir (ya da her ikisi) yapacak.

Fwiw, std::chrono::hours::period::num, 60*60 belirtmek için başka bir yol olurdu (eğer bazı C++ 11 cred :-) göstermek istiyorsanız).

Ya aslında tıpkı olabilir:

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())); 
} 

Ayrıca ben static düşmesi cazip olacaktır. Sistemimde tam olarak aynı kod static ile veya olmadan oluşturulur. Tüm derleme zamanında oluyor, bu nedenle static "sadece bir kez" başlatma semantiğine gerek yoktur.

Sadece bu berrak hale getirmek için Güncelleştirme, ben orijinal örneğini düzenlendi:

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()); 
} 

++ ++ ve libc clang -O1 (zorlukla etkin optimizasyonlar) ile derlendi ve montaj olduğunu :

.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 

sonra aynı ayarlarla bu programı derlenmiş:

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

Ve oluşturulan düzenek olan:

bu kimse bir free lunch alır gibi yaklaşık olarak yakındır Yani imho
.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 

. :-)

İlgili konular