Penulis materi, terjemahan yang kami terbitkan hari ini, mengatakan bahwa C ++, dalam bentuk modernnya, jika dibandingkan dengan apa yang beberapa tahun lalu, telah berubah secara signifikan menjadi lebih baik. Tentu saja, perubahan ini tidak terjadi segera. Misalnya, di masa lalu, C ++ tidak memiliki dinamisme. Tidak mudah menemukan seseorang yang dapat mengatakan bahwa ia memiliki perasaan yang lembut terhadap bahasa ini. Semuanya berubah ketika mereka yang bertanggung jawab untuk membakukan bahasa memutuskan untuk memberikan jalan kepada inovasi. Pada tahun 2011, C ++ menjadi bahasa yang dinamis, bahasa yang terus berkembang dan menyebabkan programmer lebih banyak emosi positif.
Jangan berpikir bahwa bahasa menjadi lebih mudah. Itu masih bisa disebut salah satu bahasa pemrograman yang paling kompleks digunakan, jika bukan yang paling kompleks. Tapi C ++ modern telah menjadi jauh lebih ramah dari sebelumnya.

Hari ini kita akan berbicara tentang beberapa fitur baru bahasa (dimulai dengan C ++ 11, yang, sudah, sudah berusia 8 tahun), yang akan diketahui oleh programmer mana pun.
Kata kunci otomatis
Sejak kata kunci
auto
muncul di C ++ 11, kehidupan programmer menjadi lebih mudah. Berkat kata kunci ini, kompiler dapat menampilkan tipe variabel pada waktu kompilasi, yang menyelamatkan kita dari selalu harus menentukan jenis sendiri. Ini ternyata sangat nyaman, misalnya, dalam kasus di mana Anda harus bekerja dengan tipe data seperti
map<string,vector<pair<int,int>>>
. Saat menggunakan kata kunci
auto
, ada beberapa hal yang perlu dipertimbangkan. Pertimbangkan sebuah contoh:
auto an_int = 26;
Perhatikan baris terakhir dalam contoh ini, komentar yang ditandai sebagai
#1
(selanjutnya, dengan cara yang sama kita akan menandai baris yang akan kita uraikan setelah contoh). Tidak ada penginisialisasi di baris ini, Anda tidak bisa melakukan ini. Kode yang terletak pada baris ini mencegah kompiler mengetahui jenis variabel yang sesuai.
Awalnya, kata kunci
auto
dalam C ++ cukup terbatas. Kemudian, dalam versi bahasa yang lebih baru, fitur yang ditambahkan secara
auto
. Ini adalah contoh lain:
auto merge(auto a, auto b)
Baris
#1
dan
#2
menggunakan inisialisasi variabel menggunakan kurung kurawal - fitur baru lainnya di C ++ 11.
Ingatlah bahwa ketika menggunakan kata kunci
auto
, kompiler harus memiliki beberapa cara untuk menyimpulkan jenis variabel.
Sekarang, pertanyaan yang menarik. Apa yang terjadi jika Anda menggunakan desain seperti
auto a = {1, 2, 3}
? Apa ini Vektor, atau penyebab kesalahan kompilasi?
Bahkan, konstruksi bentuk
std::initializer_list<type>
muncul di C ++ 11. Daftar nilai inisialisasi yang di dalam tanda kurung akan diperlakukan sebagai wadah menggunakan kata kunci
auto
.
Dan akhirnya, seperti yang telah disebutkan, ketik inferensi oleh kompiler dapat sangat berguna jika Anda harus bekerja dengan struktur data yang kompleks. Berikut ini sebuah contoh:
void populate(auto &data) {
Lihatlah baris
#1
. Ekspresi
auto [v1,v2] = itr.second
mewakili fitur baru C ++ 17. Ini adalah apa yang disebut dekomposisi ketika mendeklarasikan variabel. Dalam versi bahasa sebelumnya, setiap nilai harus diekstraksi secara terpisah. Berkat mekanisme ini, melakukan operasi seperti itu menjadi jauh lebih nyaman.
Selain itu, jika Anda perlu bekerja dengan data menggunakan tautan, cukup menambahkan hanya satu karakter ke konstruksi ini, mengonversinya ke bentuk berikut:
auto &[v1,v2] = itr.second
.
Ekspresi Lambda
C ++ 11 memperkenalkan dukungan untuk ekspresi lambda. Mereka menyerupai fungsi anonim dalam JavaScript, mereka dapat dibandingkan dengan objek fungsional tanpa nama. Mereka menangkap variabel dalam berbagai lingkup tergantung pada deskripsi mereka, yang konstruksi sintaksis kompak digunakan. Selain itu, mereka dapat ditugaskan ke variabel.
Ekspresi Lambda adalah alat yang sangat berguna untuk kasus-kasus ketika Anda perlu melakukan beberapa operasi kecil dalam kode, tetapi Anda tidak ingin menulis fungsi terpisah untuk ini. Contoh umum lain dari penggunaannya adalah penciptaan fungsi yang digunakan dalam membandingkan nilai. Sebagai contoh:
std::vector<std::pair<int,int>> data = {{1,3}, {7,6}, {12, 4}};
Anda dapat menemukan banyak hal menarik dalam contoh singkat ini.
Pertama, perhatikan betapa nyamannya menggunakan inisialisasi variabel menggunakan kurung kurawal. Selanjutnya, kita dapat melihat konstruksi standar
begin()
dan
end()
, yang juga muncul dalam C ++ 11. Kemudian muncul fungsi lambda, yang digunakan sebagai mekanisme untuk membandingkan data. Parameter fungsi ini dideklarasikan menggunakan kata kunci
auto
, fitur ini muncul di C ++ 14. Sebelumnya, kata kunci ini tidak dapat digunakan untuk menggambarkan parameter fungsi.
Sekarang perhatikan bahwa ekspresi lambda dimulai dengan tanda kurung siku -
[]
. Inilah yang disebut topeng variabel. Ini menentukan ruang lingkup ekspresi, yaitu, memungkinkan Anda untuk mengontrol hubungan ekspresi lambda dengan variabel dan objek lokal.
Berikut adalah kutipan dari repositori yang didedikasikan untuk fitur C ++ modern ini:
[]
- ekspresi tidak menangkap apa pun. Ini berarti bahwa dalam ekspresi lambda tidak mungkin untuk menggunakan variabel lokal dari ruang lingkup yang eksternal untuk itu. Hanya parameter yang dapat digunakan dalam ekspresi.[=]
- ekspresi menangkap nilai objek lokal (yaitu, variabel lokal, parameter). Ini berarti bahwa mereka dapat digunakan, tetapi tidak dimodifikasi.[&]
- ekspresi menangkap referensi ke objek lokal. Mereka dapat dimodifikasi, seperti yang ditunjukkan pada contoh berikut.[this]
- ekspresi menangkap nilai dari pointer this
.[a, &b]
- ekspresi menangkap nilai objek a
dan referensi ke objek b
.
Akibatnya, jika di dalam fungsi lambda Anda perlu mengkonversi data ke beberapa format lain, Anda dapat menggunakan mekanisme di atas. Pertimbangkan sebuah contoh:
std::vector<int> data = {2, 4, 4, 1, 1, 3, 9}; int factor = 7; for_each(begin(data), end(data), [&factor](int &val) {
Di sini, jika variabel
factor
diakses oleh nilai (maka variabel mask
[factor]
akan digunakan untuk menggambarkan ekspresi lambda), maka di baris
#1
nilai
factor
tidak dapat diubah - hanya karena kita tidak akan memiliki hak untuk melakukan operasi seperti itu. Dalam contoh ini, kami memiliki hak untuk melakukan tindakan tersebut. Dalam situasi seperti itu, penting untuk tidak menyalahgunakan kemampuan yang diakses oleh referensi variabel.
Selain itu, perhatikan bahwa
val
juga diakses dengan referensi. Ini memastikan bahwa perubahan data yang terjadi pada fungsi lambda memengaruhi
vector
.
Ekspresi inisialisasi variabel di dalam if dan switch constructs
Saya sangat menyukai inovasi C ++ 17 ini setelah saya mengetahuinya. Pertimbangkan sebuah contoh:
std::set<int> input = {1, 5, 3, 6}; if(auto it = input.find(7); it==input.end()){
Ternyata sekarang Anda dapat menginisialisasi variabel dan membandingkannya dengan penggunaannya dalam satu
if
atau
switch
blok. Ini membantu menulis kode yang akurat. Berikut ini adalah deskripsi skematis dari struktur yang sedang dipertimbangkan:
if( init-statement(x); condition(x)) {
Melakukan perhitungan waktu kompilasi menggunakan constexpr
constexpr
memberi kita peluang besar. Misalkan kita memiliki semacam ekspresi yang perlu dihitung, sedangkan nilainya, setelah menginisialisasi dengan variabel yang sesuai, tidak akan berubah. Ungkapan seperti itu dapat dihitung di muka dan digunakan sebagai makro. Atau, apa yang menjadi mungkin di C ++ 11, gunakan
constexpr
.
Programmer berusaha untuk meminimalkan jumlah perhitungan yang dilakukan selama eksekusi program. Akibatnya, jika operasi tertentu dapat dilakukan selama proses kompilasi dan dengan demikian menghapus beban dari sistem selama eksekusi program, ini akan memiliki efek yang baik pada perilaku program selama eksekusi. Berikut ini sebuah contoh:
#include <iostream> constexpr long long fact(long long n) { // constexpr return n == 1 ? 1 : (fact(n-1) * n); } int main() { const long long bigval = fact(20); std::cout<<bigval<<std::endl; }
Ini adalah contoh yang sangat umum menggunakan
constexpr
.
Karena kami mendeklarasikan fungsi untuk menghitung faktorial sebagai
constexpr
, kompiler dapat melakukan pra-perhitungan nilai
fact(20)
pada saat kompilasi program. Akibatnya, setelah dikompilasi, string
const long long bigval = fact(20);
dapat diganti dengan
const long long bigval = 2432902008176640000;
.
Perhatikan bahwa argumen yang diteruskan ke fungsi diwakili oleh konstanta. Ini adalah fitur penting menggunakan fungsi yang dideklarasikan menggunakan
constexpr
. Argumen yang disampaikan kepada mereka juga harus dideklarasikan dengan
constexpr
atau dengan kata kunci
const
. Jika tidak, fungsi tersebut akan berperilaku seperti fungsi biasa, yaitu, selama kompilasi, nilainya tidak akan dihitung sebelumnya.
Variabel juga dapat dideklarasikan menggunakan
constexpr
. Dalam hal ini, seperti yang Anda duga, nilai-nilai variabel ini harus dihitung pada waktu kompilasi. Jika ini tidak dapat dilakukan, pesan kesalahan kompilasi akan ditampilkan.
Sangat menarik untuk dicatat bahwa kemudian, dalam C ++ 17,
konstruksi constexpr-if dan
constexpr-lambda muncul.
Struktur data Tuple
Seperti struktur data
pair
, struktur data
tuple
(tuple) adalah kumpulan nilai dari berbagai jenis ukuran tetap. Berikut ini sebuah contoh:
auto user_info = std::make_tuple("M", "Chowdhury", 25);
Terkadang, alih-alih struktur data
tuple
, lebih nyaman menggunakan
std::array
. Struktur data ini mirip dengan array sederhana yang digunakan dalam bahasa C, dilengkapi dengan fitur tambahan dari pustaka standar C ++. Struktur data ini muncul di C ++ 11.
Secara otomatis menyimpulkan tipe argumen templat kelas
Nama fitur ini terlihat agak panjang dan kompleks, tetapi sebenarnya tidak ada yang rumit di sini. Gagasan utama di sini adalah bahwa dalam C ++ 17, output dari tipe argumen template juga dilakukan untuk templat kelas standar. Sebelumnya, ini hanya didukung untuk templat fungsional. Alhasil, ternyata mereka biasa menulis seperti ini:
std::pair<std::string, int> user = {"M", 25};
Dengan rilis C ++ 17, konstruksi ini sekarang dapat diganti dengan ini:
std::pair user = {"M", 25};
Jenis inferensi dilakukan secara implisit. Mekanisme ini bahkan lebih nyaman digunakan untuk tupel. Yaitu, sebelum saya harus menulis yang berikut:
std::tuple<std::string, std::string, int> user ("M", "Chy", 25);
Sekarang hal yang sama terlihat seperti ini:
std::tuple user2("M", "Chy", 25);
Perlu dicatat bahwa fitur-fitur ini tidak akan terlihat menarik bagi mereka yang tidak terlalu mengenal template C ++.
Pointer pintar
Bekerja dengan pointer di C ++ bisa menjadi mimpi buruk yang nyata. Berkat kebebasan yang diberikan oleh bahasa kepada programmer, kadang-kadang sangat sulit baginya, seperti yang mereka katakan, "untuk tidak menembak diri sendiri." Dalam banyak kasus, pointer mendorong "tembakan" programmer.
Untungnya, C ++ 11 memperkenalkan pointer pintar yang jauh lebih nyaman daripada pointer biasa. Mereka membantu programmer menghindari kebocoran memori dengan membebaskan sumber daya bila memungkinkan. Selain itu, mereka memberikan jaminan keamanan untuk pengecualian.
Ringkasan
Berikut adalah repositori yang baik, yang kami percaya, akan menarik untuk dikunjungi oleh mereka yang mengikuti inovasi C ++. Sesuatu yang baru terus muncul dalam bahasa ini. Di sini kami menyentuh hanya beberapa fitur modern bahasa. Padahal, ada banyak dari mereka. Mungkin saja kita masih membicarakannya.
Pembaca yang budiman! Apa fitur C ++ modern yang menurut Anda paling menarik dan berguna?
