Saya membaca Accelerated C ++ oleh Koenig. Dia menulis bahwa "ide barunya adalah kita dapat menggunakan + untuk menggabungkan string dan string literal - atau, dalam hal ini, dua string (tapi bukan dua string literal).
Baiklah, kurasa ini masuk akal. Sekarang ke dua latihan terpisah yang dimaksudkan untuk menerangi ini.
Apakah definisi berikut ini valid?
const string hello = "Hello";
const string message = hello + ",world" + "!";
Sekarang, saya mencoba menjalankan yang di atas dan berhasil! Jadi saya senang.
Kemudian saya mencoba melakukan latihan berikutnya;
const string exclam = "!";
const string message = "Hello" + ",world" + exclam;
Ini tidak berhasil. Sekarang saya mengerti itu ada hubungannya dengan fakta bahwa Anda tidak dapat menggabungkan dua string literal, tetapi saya tidak mengerti perbedaan semantik antara mengapa saya berhasil mendapatkan contoh pertama untuk bekerja (bukan ", dunia" dan "! "dua string literal? Bukankah seharusnya ini tidak berhasil?) tapi tidak yang kedua.
const string message = "Hello" ",world" + exclam
(misalnya menghilangkan yang pertama+
) harus bekerja dengan baik."Hello" + ", world!"
ketika Anda bisa melakukannya"Hello, world!"
. Seperti biasa C ++ memiliki solusi yang luar biasa dan sederhana untuk masalah yang dirasakan. :-)"Hello" ", world!"
(tanpa+
). Ada sejumlah keluhan yang bisa dibuat tentang C ++, tapi menurut saya penanganannya di sini bukan salah satunya. Persis sama seperti jika Anda menulis1 / 3 + 1.5
, dan mengeluh karena divisi itu adalah divisi integral. Baik atau buruk, inilah cara kebanyakan bahasa bekerja."hello" " world" == "hello world"
ini berguna jika Anda harus menulis string yang panjang dan tidak ingin keluar dari jendela Anda atau Anda ingin berada dalam penyempitan panjang baris. Atau jika salah satu string ditentukan dalam makro.Jawaban:
The
+
Operator telah kiri ke kanan associativity, sehingga ekspresi kurung setara adalah:Seperti yang Anda lihat, dua string literal
"Hello"
dan",world"
"ditambahkan" terlebih dahulu, maka kesalahannya.Salah satu dari dua string pertama yang digabungkan harus berupa
std::string
objek:Cara lainnya, Anda dapat memaksa yang kedua
+
untuk dievaluasi terlebih dahulu dengan memberi tanda kurung bagian ekspresi tersebut:Masuk akal bahwa contoh pertama Anda (
hello + ",world" + "!"
) berfungsi karenastd::string
(hello
) adalah salah satu argumen paling kiri+
. Itu+
dievaluasi, hasilnya adalahstd::string
objek dengan string yang digabungkan, dan yang dihasilkanstd::string
kemudian digabungkan dengan"!"
.Adapun mengapa Anda tidak dapat menggabungkan dua string literal menggunakan
+
, itu karena literal string hanyalah sebuah array karakter (diconst char [N]
manaN
panjang string ditambah satu, untuk terminator null). Saat Anda menggunakan larik di sebagian besar konteks, larik akan diubah menjadi penunjuk ke elemen awalnya.Jadi, ketika Anda mencoba melakukannya
"Hello" + ",world"
, yang sebenarnya Anda coba lakukan adalah menambahkan duaconst char*
bersama, yang tidak mungkin (apa artinya menambahkan dua petunjuk bersama-sama?) Dan jika itu tidak akan melakukan apa yang Anda lakukan. ingin melakukannya.Perhatikan bahwa Anda dapat menggabungkan string literal dengan menempatkannya di samping satu sama lain; misalnya, dua hal berikut ini setara:
Ini berguna jika Anda memiliki literal string panjang yang ingin Anda bagi menjadi beberapa baris. Namun, mereka harus berupa string literal: ini tidak akan berfungsi dengan
const char*
pointer atauconst char[N]
array.sumber
const string message = "Hello" + (",world"+exclam);
akan bekerja juga, karena tanda kurung eksplisit (apakah itu sebuah kata?).const string message = ((hello + ",world") + "!");
"Hello" ",world"
sintaks ini berguna tidak hanya untuk memecah menjadi beberapa baris tetapi juga ketika salah satu literal string adalah makro (atau bahkan keduanya). Kemudian penggabungan terjadi dalam waktu kompilasi.Anda harus selalu memperhatikan jenisnya .
Meskipun semuanya tampak seperti string,
"Hello"
dan",world"
bersifat literal .Dan dalam contoh Anda,
exclam
adalah sebuahstd::string
objek.C ++ memiliki operator overload yang mengambil
std::string
objek dan menambahkan string lain ke dalamnya. Saat Anda menggabungkanstd::string
objek dengan literal, itu akan membuat casting yang sesuai untuk literal.Tetapi jika Anda mencoba untuk menggabungkan dua literal, kompilator tidak akan dapat menemukan operator yang membutuhkan dua literal.
sumber
std::string
dengan yang lainstd::string
, larik karakter, atau satu karakter.Contoh kedua Anda tidak berfungsi karena tidak ada
operator +
untuk dua string literal. Perhatikan bahwa string literal bukanlah bertipestring
, melainkan bertipeconst char *
. Contoh kedua Anda akan berhasil jika Anda merevisinya seperti ini:sumber
Sejak C ++ 14 Anda dapat menggunakan dua literal string nyata :
atau
sumber
Dalam kasus 1, karena urutan operasi Anda mendapatkan:
(halo + ", dunia") + "!" yang memutuskan untuk halo + "!" dan akhirnya menyapa
Dalam kasus 2, seperti yang dicatat James, Anda mendapatkan:
("Halo" + ", dunia") + seru yang merupakan gabungan dari 2 string literal.
Semoga jelas :)
sumber
Perbedaan antara string (atau tepatnya,
std::string
) dan literal karakter adalah tidak ada+
operator yang ditentukan. Inilah mengapa contoh kedua gagal.Dalam kasus pertama, kompilator dapat menemukan yang cocok
operator+
dengan argumen pertama adalah astring
dan yang kedua adalah karakter literal (const char*
) sehingga digunakan itu. Hasil dari operasi itu lagi-lagi astring
, jadi ini mengulangi trik yang sama saat menambahkannya"!"
.sumber