Jawaban singkatnya adalah bahwa tidak hanya static
berguna, itu cukup baik selalu akan diinginkan.
Pertama, perhatikan itu static
dan constexpr
sepenuhnya independen satu sama lain. static
mendefinisikan umur objek selama eksekusi; constexpr
menentukan bahwa objek harus tersedia selama kompilasi. Kompilasi dan eksekusi saling terpisah dan terpisah, baik dalam waktu maupun ruang. Jadi begitu program dikompilasi, constexpr
tidak lagi relevan.
Setiap variabel yang dideklarasikan constexpr
secara implisit const
tetapi const
dan static
hampir ortogonal (kecuali untuk interaksi dengan static const
bilangan bulat).
Model C++
objek (§1.9) mensyaratkan bahwa semua objek selain dari bit-field menempati setidaknya satu byte memori dan memiliki alamat; selanjutnya semua objek yang dapat diamati dalam program pada saat tertentu harus memiliki alamat yang berbeda (paragraf 6). Ini tidak cukup membutuhkan kompilator untuk membuat array baru di stack untuk setiap pemanggilan fungsi dengan array const non-statis lokal, karena kompiler dapat berlindung pada as-if
prinsip asalkan dapat membuktikan bahwa tidak ada objek lain yang dapat dibuat. diamati.
Sayangnya, itu tidak mudah dibuktikan, kecuali fungsinya sepele (misalnya, tidak memanggil fungsi lain yang badannya tidak terlihat di dalam unit terjemahan) karena array, kurang lebih menurut definisi, adalah alamat. Jadi dalam kebanyakan kasus, const(expr)
array non-statis harus dibuat ulang pada stack di setiap doa, yang mengalahkan titik untuk dapat menghitungnya pada waktu kompilasi.
Di sisi lain, static const
objek lokal dibagi oleh semua pengamat, dan selanjutnya dapat diinisialisasi bahkan jika fungsi yang didefinisikan tidak pernah disebut. Jadi tidak ada satu pun di atas yang berlaku, dan kompiler bebas tidak hanya untuk menghasilkan hanya satu instance saja; itu gratis untuk menghasilkan satu contoh dari itu dalam penyimpanan read-only.
Jadi, Anda harus menggunakan static constexpr
contoh Anda.
Namun, ada satu kasus di mana Anda tidak ingin menggunakannya static constexpr
. Kecuali constexpr
objek yang dideklarasikan digunakan atau dideklarasikan ODRstatic
, kompiler bebas untuk tidak memasukkannya sama sekali. Itu cukup berguna, karena memungkinkan penggunaan constexpr
array sementara waktu kompilasi tanpa mencemari program yang dikompilasi dengan byte yang tidak perlu. Dalam hal ini, Anda jelas tidak ingin menggunakan static
, karena static
kemungkinan akan memaksa objek ada saat runtime.
const
dariconst
objek, hanya dariconst X*
yang menunjuk ke suatuX
. Tapi bukan itu intinya; intinya adalah bahwa objek otomatis tidak dapat memiliki alamat statis. Seperti yang saya katakan,constexpr
berhenti menjadi bermakna setelah kompilasi selesai, jadi tidak ada yang dibuang (dan sangat mungkin tidak ada sama sekali, karena objek tersebut bahkan tidak dijamin ada saat runtime.)static
danconstexpr
tetapi jelaskan bahwa mereka ortogonal dan mandiri, melakukan hal-hal yang berbeda. Anda kemudian menyebutkan alasan untuk TIDAK menggabungkan keduanya karena akan mengabaikan penggunaan ODR (yang tampaknya berguna). Oh dan saya masih tidak melihat mengapa statis harus digunakan dengan constexpr karena statis untuk hal-hal runtime. Anda tidak pernah menjelaskan mengapa statis dengan constexpr itu penting.static constexpr
(itu mencegah array konstan harus diciptakan kembali pada setiap panggilan fungsi), tetapi saya mengubah beberapa kata yang mungkin membuatnya lebih jelas. Terima kasih.constexpr
variabel konstan hanya digunakan dalam konteks waktu kompilasi dan tidak pernah diperlukan saat runtime, makastatic
tidak masuk akal, karena pada titik Anda sampai ke runtime, nilainya telah secara efektif "digariskan". Namun, jikaconstexpr
digunakan dalam konteks runtime (dengan kata lain, yangconstexpr
perlu dikonversiconst
secara implisit, dan tersedia dengan alamat fisik untuk kode runtime) itu akan inginstatic
memastikan kepatuhan ODR, dll. Itulah pemahaman saya, setidaknya.static constexpr int foo = 100;
. Tidak ada alasan mengapa kompiler tidak dapat menggantikan penggunaan difoo
mana-mana dengan literal100
, kecuali kode melakukan sesuatu seperti&foo
. Jadistatic
padafoo
tidak memiliki kegunaan dalam kasus ini karenafoo
tidak ada pada saat runtime. Sekali lagi semuanya sampai ke kompiler.Selain jawaban yang diberikan, perlu dicatat bahwa kompiler tidak diharuskan untuk menginisialisasi
constexpr
variabel pada waktu kompilasi, mengetahui bahwa perbedaan antaraconstexpr
danstatic constexpr
apakah untuk menggunakanstatic constexpr
Anda memastikan variabel diinisialisasi hanya sekali.Kode berikut menunjukkan bagaimana
constexpr
variabel diinisialisasi beberapa kali (dengan nilai yang sama), sedangkanstatic constexpr
pasti diinisialisasi hanya sekali.Selain itu, kode membandingkan keuntungan
constexpr
melawanconst
dalam kombinasi denganstatic
.Output program yang mungkin:
Seperti yang Anda lihat sendiri,
constexpr
beberapa kali tidakstatic
diinisiasi (alamat tidak sama) sementara kata kunci memastikan bahwa inisialisasi dilakukan hanya sekali.sumber
constexpr const short constexpr_short
untuk memberikan kesalahan jika constexpr_short diinisialisasi lagiconstexpr const
tidak masuk akal karenaconstexpr
sudah adaconst
, menambahkanconst
sekali atau beberapa kali diabaikan oleh kompiler. Anda mencoba menangkap kesalahan tetapi ini bukan kesalahan, itulah cara kerja kebanyakan kompiler.