Pada pertemuan Oulu ISO C ++ Standards 2016, sebuah proposal yang disebut Variabel Inline dipilih menjadi C ++ 17 oleh komite standar.
Dalam istilah awam, apa itu variabel sebaris, bagaimana cara kerjanya dan untuk apa mereka berguna? Bagaimana variabel sebaris harus dideklarasikan, ditentukan dan digunakan?
const
.inline
kata kunci untuk fungsi. Katainline
kunci, bila diterapkan ke fungsi, memiliki satu efek penting lainnya, yang diterjemahkan langsung ke variabel. Sebuahinline
fungsi, yang mungkin dideklarasikan dalam file header, tidak akan menghasilkan kesalahan "simbol duplikat" pada waktu penautan, meskipun header tersebut#include
d oleh beberapa unit terjemahan. Katainline
kunci, bila diterapkan ke variabel, akan memiliki hasil yang persis sama. Tamat.inline
hanya permintaan yang lemah dan tidak mengikat ke pengoptimal. Penyusun bebas untuk tidak menyebariskan fungsi yang diminta dan / atau ke sebaris yang tidak Anda beri anotasi. Sebaliknya, tujuan sebenarnya dariinline
kata kunci tersebut adalah untuk menghindari kesalahan definisi ganda.Jawaban:
Kalimat pertama proposal:
Efek ¹ dijamin
inline
seperti yang diterapkan ke suatu fungsi, adalah memungkinkan fungsi didefinisikan secara identik, dengan tautan eksternal, dalam beberapa unit terjemahan. Untuk in-practice artinya mendefinisikan fungsi dalam sebuah header, yang dapat dimasukkan ke dalam beberapa unit terjemahan. Proposal memperluas kemungkinan ini ke variabel.Jadi, dalam istilah praktis proposal (sekarang diterima) memungkinkan Anda menggunakan
inline
kata kunci untuk menentukanconst
variabel cakupan namespace tautan eksternal , ataustatic
anggota data kelas apa pun , dalam file header, sehingga beberapa definisi yang dihasilkan saat header itu disertakan dalam beberapa unit terjemahan tidak masalah dengan penaut - ini hanya memilih salah satunya.Hingga dan termasuk C ++ 14 mesin internal untuk ini telah ada, untuk mendukung
static
variabel dalam templat kelas, tetapi tidak ada cara yang nyaman untuk menggunakan mesin itu. Seseorang harus menggunakan trik sepertiDari C ++ 17 dan seterusnya saya percaya seseorang dapat menulis dengan adil
… Di file header.
Proposal mencakup kata-kata
… Yang memungkinkan hal di atas lebih disederhanakan menjadi adil
… Sebagaimana dicatat oleh TC dalam komentar untuk jawaban ini.
Selain itu,
constexpr
penentu menyiratkaninline
untuk anggota data statis serta fungsi.Catatan:
¹ Karena suatu fungsi
inline
juga memiliki efek petunjuk tentang pengoptimalan, kompilator harus memilih untuk mengganti panggilan fungsi ini dengan substitusi langsung dari kode mesin fungsi tersebut. Petunjuk ini bisa diabaikan.sumber
Kath::hi
) tidak harus berupa const.const
pembatasan dihapus seluruhnya.static std::string const hi = "Zzzzz...";
?Variabel sebaris sangat mirip dengan fungsi sebaris. Ini memberi sinyal kepada linker bahwa hanya satu instance dari variabel yang harus ada, meskipun variabel tersebut terlihat di beberapa unit kompilasi. Linker perlu memastikan bahwa tidak ada lagi salinan yang dibuat.
Variabel sebaris dapat digunakan untuk menentukan global di perpustakaan hanya header. Sebelum C ++ 17, mereka harus menggunakan solusi (fungsi inline atau peretasan template).
Misalnya, salah satu solusinya adalah menggunakan singleton Meyer dengan fungsi inline:
Ada beberapa kelemahan dengan pendekatan ini, sebagian besar dalam hal kinerja. Overhead ini dapat dihindari dengan solusi template, tetapi mudah untuk salah.
Dengan variabel sebaris, Anda dapat langsung mendeklarasikannya (tanpa mendapatkan kesalahan linker definisi ganda):
Selain pustaka hanya header, ada kasus lain di mana variabel sebaris dapat membantu. Nir Friedman membahas topik ini dalam ceramahnya di CppCon: Apa yang harus diketahui developer C ++ tentang global (dan linker) . Bagian tentang variabel sebaris dan penyelesaiannya dimulai pada 18m9s .
Singkat cerita, jika Anda perlu mendeklarasikan variabel global yang dibagikan di antara unit kompilasi, mendeklarasikannya sebagai variabel sebaris di file header sangatlah mudah dan menghindari masalah dengan solusi pra-C ++ 17.
(Masih ada kasus penggunaan untuk singleton Meyer, misalnya, jika Anda secara eksplisit ingin memiliki inisialisasi malas.)
sumber
Contoh minimal runnable
Fitur C ++ 17 yang luar biasa ini memungkinkan kita untuk:
constexpr
: Bagaimana cara mendeklarasikan constexpr extern?main.cpp
notmain.hpp
notmain.cpp
Kompilasi dan jalankan:
GitHub upstream .
Lihat juga: Bagaimana cara kerja variabel sebaris?
Standar C ++ pada variabel sebaris
Standar C ++ menjamin bahwa alamatnya akan sama. C ++ 17 N4659 standard draft 10.1.6 "The inline specifier":
cppreference https://en.cppreference.com/w/cpp/language/inline menjelaskan bahwa jika
static
tidak diberikan, maka ia memiliki tautan eksternal.Penerapan variabel sebaris GCC
Kita dapat mengamati bagaimana ini diterapkan dengan:
yang mengandung:
dan
man nm
mengatakan tentangu
:jadi kami melihat bahwa ada ekstensi ELF khusus untuk ini.
Pra-C ++ 17:
extern const
Sebelum C ++ 17, dan di C, kita dapat mencapai efek yang sangat mirip dengan sebuah
extern const
, yang akan mengarah ke satu lokasi memori yang digunakan.Kerugiannya
inline
adalah:constexpr
dengan teknik ini, hanyainline
memungkinkan: Bagaimana cara mendeklarasikan constexpr extern?main.cpp
notmain.cpp
notmain.hpp
GitHub upstream .
Alternatif header saja Pre-C ++ 17
Ini tidak sebaik
extern
solusinya, tetapi berfungsi dan hanya menggunakan satu lokasi memori:Sebuah
constexpr
fungsi, karenaconstexpr
menyiratkaninline
daninline
memungkinkan (memaksa) definisi tersebut muncul di setiap unit terjemahan :dan saya yakin bahwa setiap kompilator yang layak akan melakukan panggilan inline.
Anda juga dapat menggunakan variabel integer
const
atauconstexpr
statis seperti di:tetapi Anda tidak dapat melakukan hal-hal seperti mengambil alamatnya, atau menjadi digunakan odr, lihat juga: https://en.cppreference.com/w/cpp/language/static "Anggota statis konstan" dan Menentukan data statis constexpr anggota
C
Dalam C situasinya sama dengan C ++ sebelum C ++ 17, saya telah mengunggah contoh di: Apa artinya "statis" di C?
Satu-satunya perbedaan adalah bahwa dalam C ++,
const
menyiratkanstatic
untuk GLOBALS, tapi tidak di C: C ++ semantik `const` statis vs` const`Adakah cara untuk membuatnya sebaris sepenuhnya?
TODO: apakah ada cara untuk menyebariskan variabel sepenuhnya, tanpa menggunakan memori sama sekali?
Mirip seperti yang dilakukan preprocessor.
Ini akan membutuhkan entah bagaimana:
Terkait:
Diuji di Ubuntu 18.10, GCC 8.2.0.
sumber
inline
hampir tidak ada hubungannya dengan inlining, baik untuk fungsi maupun variabel, terlepas dari kata itu sendiri.inline
tidak memberi tahu kompilator untuk menyebariskan apa pun. Ini memberitahu linker untuk memastikan bahwa hanya ada satu definisi, yang secara tradisional merupakan tugas programmer. Jadi, "Adakah cara untuk menyebarnya sepenuhnya?" setidaknya merupakan pertanyaan yang sama sekali tidak berhubungan.