Saya tidak berpikir salah satu jawaban benar-benar menjelaskan dengan tepat apa efek sampingnya, atau memang, apa itu.
constexprdan constpada namespace / file-scope identik ketika diinisialisasi dengan literal atau ekspresi; tetapi dengan suatu fungsi, constdapat diinisialisasi dengan fungsi apa pun, tetapi constexprdiinisialisasi oleh non-constexpr (fungsi yang tidak ditandai dengan constexpr atau ekspresi non constexpr) akan menghasilkan kesalahan kompilator. Keduanya constexprdan constmerupakan keterkaitan internal implisit untuk variabel (yah sebenarnya, mereka tidak bertahan untuk sampai ke tahap menghubungkan jika kompilasi -O1 dan lebih kuat, dan statictidak memaksa kompiler untuk memancarkan simbol penghubung internal (lokal) untuk constatau constexprketika pada -O1 atau lebih kuat, satu-satunya waktu melakukan ini adalah jika Anda mengambil alamat variabel, constdan constexprakan menjadi simbol internal kecuali dinyatakan dengan externieextern constexpr/const int i = 3;perlu digunakan). Pada suatu fungsi, constexprmembuat fungsi secara permanen tidak pernah mencapai tahap menghubungkan (terlepas dari externatau inlinedalam definisi atau -O0 atau -Ofast), sedangkan consttidak pernah melakukannya, dan staticdan inlinehanya memiliki efek ini pada -O1 dan di atas. Ketika a const/ constexprvariabel diinisialisasi oleh suatu constexprfungsi, beban selalu dioptimalkan dengan flag optimasi apa pun, tetapi itu tidak pernah dioptimalkan jika fungsi hanya staticatau inline, atau jika variabel bukan a const/ constexpr.
Kompilasi standar (-O0)
#include<iostream>
constexpr int multiply (int x, int y)
{
return x * y;
}
extern const int val = multiply(10,10);
int main () {
std::cout << val;
}
kompilasi ke
val:
.long 100 //extra external definition supplied due to extern
main:
push rbp
mov rbp, rsp
mov esi, 100 //substituted in as an immediate
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov eax, 0
pop rbp
ret
__static_initialization_and_destruction_0(int, int):
.
.
.
Namun
#include<iostream>
const int multiply (int x, int y)
{
return x * y;
}
const int val = multiply(10,10); //constexpr is an error
int main () {
std::cout << val;
}
Kompilasi ke
multiply(int, int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov eax, DWORD PTR [rbp-4]
imul eax, DWORD PTR [rbp-8]
pop rbp
ret
main:
push rbp
mov rbp, rsp
mov eax, DWORD PTR val[rip]
mov esi, eax
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov eax, 0
pop rbp
ret
__static_initialization_and_destruction_0(int, int):
.
.
.
mov esi, 10
mov edi, 10
call multiply(int, int)
mov DWORD PTR val[rip], eax
Ini jelas menunjukkan bahwa constexprmenyebabkan inisialisasi const/constexprvariabel file-lingkup terjadi pada waktu kompilasi dan tidak menghasilkan simbol global, sedangkan tidak menggunakannya menyebabkan inisialisasi terjadi sebelum mainsaat runtime.
Kompilasi menggunakan -Ofast
Bahkan -Ofast tidak mengoptimalkan beban! https://godbolt.org/z/r-mhif , jadi Anda perlu constexpr
constexpr fungsi juga bisa dipanggil dari dalam lainnya constexpr fungsi untuk hasil yang sama. constexprpada suatu fungsi juga mencegah penggunaan apa pun yang tidak dapat dilakukan pada waktu kompilasi dalam fungsi; misalnya, panggilan ke <<operator aktif std::cout.
constexprpada lingkup blok berperilaku sama karena menghasilkan kesalahan jika diinisialisasi oleh fungsi non-constexpr; nilainya juga diganti segera.
Pada akhirnya, tujuan utamanya adalah seperti fungsi inline C, tetapi hanya efektif ketika fungsi tersebut digunakan untuk menginisialisasi variabel lingkup file (yang fungsi tidak dapat dilakukan pada C, tetapi mereka dapat pada C ++ karena memungkinkan inisialisasi dinamis file- variabel lingkup), kecuali fungsi tidak dapat mengekspor simbol global / lokal ke linker juga, bahkan menggunakan extern/static, yang Anda bisa dengan inlinedi C; fungsi penugasan variabel blok-lingkup dapat diuraikan hanya dengan menggunakan optimasi -O1 tanpa constexprpada C dan C ++.
constexprmenciptakan konstanta waktu kompilasi;consthanya berarti bahwa nilai tidak dapat diubah.