2013-04-09 15 views
5

Tôi có chức năng khá đơn giản này, tôi có một số giá trị cần được tính toán nhưng chỉ một lần và thời gian tốt nhất là lúc biên dịch. Những giá trị này chỉ quan trọng trong hàm này. Đây có phải là một sử dụng tốt của constexpr hay tôi chỉ cần khai báo chúng const tĩnh?Tôi có nên sử dụng constexpr như thế này không?

ps Tôi biết rằng sự khác biệt hiệu suất là quá ít để không quan trọng, nhưng tôi muốn làm điều đó "Quyền" C++ 11 cách.

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' ngụ ý' const'. – Xeo

+1

'const int' là đủ cho mọi, nhưng' constexpr int' có thể rõ ràng hơn. Xin vui lòng không trộn hai. – ipc

+0

Không phải là một const int tạo ra và bị phá hủy mỗi khi chức năng được gọi là, và do đó các tính toán phải được thực hiện là tốt? Tôi biết nó có thể được tối ưu hóa, nhưng tôi muốn đúng nó để mã nói chính xác những gì tôi đang ngụ ý. – EddieV223

Trả lời

7

Việc sử dụng của bạn tốt, nếu không phải là một chút tiết. Trong ngữ cảnh này, constexprconst có nghĩa là chính xác điều tương tự. Hoặc là một (hoặc thậm chí cả hai) sẽ làm.

Fwiw, std::chrono::hours::period::num sẽ là một cách khác để chỉ định 60*60 (nếu bạn muốn hiển thị một số tín dụng C++ 11 :-)).

Hoặc thực sự bạn chỉ có thể làm:

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

Ngoài ra tôi muốn được cám dỗ để thả các static. Trên hệ thống của tôi, mã chính xác được tạo ra có hoặc không có static. Tất cả đều diễn ra vào thời gian biên dịch, vì vậy không cần thiết cho ngữ nghĩa khởi tạo "một lần duy nhất" một lần duy nhất.

Cập nhật

Chỉ cần để làm cho tinh này rõ ràng, tôi thay đổi nội dung ví dụ ban đầu để:

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

Biên soạn nó với -O1 (tối ưu hóa hầu như không được kích hoạt) với kêu vang ++ và libC++ và lắp ráp là :

.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 

Sau đó, tôi đã biên soạn chương trình này với cùng cài đặt:

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

Và lắp ráp tạo ra là:

.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 

Vì vậy, IMHO này là khoảng gần như ai được đến một free lunch. :-)