Pertimbangkan fungsi sebaris berikut:
// Inline specifier version
#include<iostream>
#include<cstdlib>
inline int f(const int x);
inline int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
dan versi yang setara dengan constexpr:
// Constexpr specifier version
#include<iostream>
#include<cstdlib>
constexpr int f(const int x);
constexpr int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
Pertanyaan saya adalah: apakah constexpr
penspesifikasi menyiratkan inline
penentu dalam arti bahwa jika argumen non-konstan dilewatkan ke suatu constexpr
fungsi, kompilator akan mencoba inline
fungsi tersebut seolah-olah inline
penentu itu dimasukkan ke dalam deklarasinya?
Apakah standar C ++ 11 menjamin itu?
inline
penspesifikasi. (Atau mungkin saya salah memahami ungkapan Anda.)inline
specifier tidak lagi ada hubungannya dengan sebarisinline
berhubungan langsung dengan inlining. Jadi tidak ada, yangconstexpr
specifier tidak berartiinline
specifier dalam arti bahwa, sebagai yang rasa tidak ada.Jawaban:
Ya ([dcl.constexpr], §7.1.5 / 2 dalam standar C ++ 11): "fungsi constexpr dan konstruktor constexpr secara implisit sebaris (7.1.2)."
Perhatikan, bagaimanapun, bahwa
inline
penentu benar-benar memiliki sangat sedikit (jika ada) efek pada apakah kompilator akan memperluas fungsi sebaris atau tidak. Namun, hal itu memengaruhi aturan satu definisi, dan dari perspektif itu, kompilator diharuskan mengikuti aturan yang sama untuk suatuconstexpr
fungsi sebagaiinline
fungsi.Saya juga harus menambahkan bahwa terlepas dari
constexpr
menyiratkaninline
, aturan untukconstexpr
fungsi di C ++ 11 mengharuskannya cukup sederhana sehingga sering kali merupakan kandidat yang baik untuk perluasan sebaris (pengecualian utama adalah yang rekursif). Namun, sejak itu, aturan menjadi semakin longgar, sehinggaconstexpr
dapat diterapkan ke fungsi yang jauh lebih besar dan lebih kompleks.sumber
constexpr
fungsi tidak akan menyebabkan pembuatan kode sama sekali ...constexpr
Fungsi @KerrekSB berpotensi dievaluasi pada waktu kompilasi. Namun standar C ++ 14 dikotori dengan standar yang kemungkinan besar akan dipanggil saat runtime. Misalnya:std::array<T,N>::at
constexpr
tidak menyiratkaninline
untuk variabel non-statis (variabel sebaris C ++ 17)Meskipun
constexpr
menyiratkaninline
untuk fungsi, itu tidak memiliki efek itu untuk variabel non-statis, mengingat variabel sebaris C ++ 17.Misalnya, jika Anda mengambil contoh minimal yang saya posting di: Bagaimana cara kerja variabel sebaris? dan hapus
inline
, biarkan sajaconstexpr
, maka variabel mendapat banyak alamat, yang merupakan hal utama yang dihindari variabel sebaris.constexpr
variabel statis bagaimanapun secara implisit statis.Contoh minimal yang
constexpr
menyiratkaninline
untuk fungsiSeperti disebutkan di: https://stackoverflow.com/a/14391320/895245 efek utama dari
inline
tidak sebaris tetapi untuk memungkinkan beberapa definisi fungsi, kutipan standar di: Bagaimana file header C ++ menyertakan implementasi?Kita dapat mengamati itu dengan memainkan contoh berikut:
main.cpp
notmain.hpp
notmain.cpp
Kompilasi dan jalankan:
Jika kami menghapus
inline
darishared_func
, tautan akan gagal dengan:karena tajuk disertakan ke dalam banyak
.cpp
file.Tetapi jika kita ganti
inline
denganconstexpr
, maka berfungsi lagi, karenaconstexpr
juga mengandung artiinline
.GCC mengimplementasikannya dengan menandai simbol sebagai lemah pada file objek ELF: Bagaimana file header C ++ menyertakan implementasi?
Diuji di GCC 8.3.0.
sumber
constexpr
masih sebaris. cppreference.com : Variabel anggota statis (tetapi bukan variabel cakupan ruang nama) yang dideklarasikanconstexpr
secara implisit adalah variabel sebaris.