Setiap kali sebuah fungsi menerima std::string, compiler menyalin teksnya — bahkan ketika fungsi itu cuma ingin membaca, misalnya menghitung jumlah kata. Untuk teks sepanjang beberapa karakter, salinan itu tidak terasa; untuk log berukuran megabyte yang diteruskan ke banyak fungsi, salinan berulang menjadi pemborosan nyata. C++17 menjawab kebutuhan ini dengan std::string_view (header <string_view>): sebuah view, yaitu jendela baca-saja yang menunjuk teks milik pihak lain tanpa memiliki dan tanpa menyalinnya. Pada Chapter ini kita memakai string_view sebagai parameter fungsi yang hemat, mempelajari operasi potongnya yang nyaris gratis, dan memahami satu bahaya khas yang harus dihindari: view ke teks yang sudah tidak hidup.

View, Bukan Salinan #

std::string_view hanya menyimpan dua informasi: alamat awal teks dan panjangnya. Karena tidak memiliki data, membuat view nyaris tanpa biaya — kontras dengan std::string yang menyalin isi ke memori sendiri. Program berikut memperagakan penggunaannya:

cpp
#include <iostream>
#include <string>
#include <string_view>

// Parameter string_view by value: hanya menyalin alamat + panjang (murah)
int hitungKata(std::string_view teks) {
    if (teks.empty()) return 0;

    int jumlah = 1;
    for (char c : teks) {
        if (c == ' ') ++jumlah;
    }
    return jumlah;
}

int main() {
    std::string kalimat = "belajar cpp itu menyenangkan";

    // view tidak menyalin isi; ia hanya menunjuk string milik kalimat
    std::string_view v = kalimat;
    std::cout << "view               : " << v << "\n";
    std::cout << "kata (dari string) : " << hitungKata(v) << "\n";

    // bisa dibuat langsung dari literal, juga tanpa salinan
    std::cout << "kata (dari literal): "
              << hitungKata("satu dua tiga empat") << "\n";

    // substr milik string_view TIDAK menyalin — hanya menggeser jendela
    std::string_view potongan = v.substr(8, 3);
    std::cout << "potongan           : " << potongan << "\n";

    // remove_prefix / remove_suffix memangkas jendela dari ujung
    std::string_view w = kalimat;
    w.remove_prefix(8);   // buang 8 karakter pertama dari jendela
    w.remove_suffix(13);  // buang 13 karakter terakhir dari jendela
    std::cout << "tengah             : " << w << "\n";

    // ukuran tipe: string_view lebih ramping dari std::string
    std::cout << "sizeof(std::string)      : " << sizeof(std::string)
              << " byte\n";
    std::cout << "sizeof(std::string_view) : " << sizeof(std::string_view)
              << " byte\n";

    return 0;
}

Output yang Dihasilkan:

text
view               : belajar cpp itu menyenangkan
kata (dari string) : 4
kata (dari literal): 4
potongan           : cpp
tengah             : cpp itu
sizeof(std::string)      : 32 byte
sizeof(std::string_view) : 16 byte

Mari kita bedah:

  1. Baris 6 (int hitungKata(std::string_view teks)): fungsi menerima teks apa pun — std::string, literal, atau potongan — tanpa menyalin isinya. Bandingkan dengan parameter std::string yang menyalin seluruh teks setiap kali dipanggil.
  2. Baris 16-17 (std::string_view v = kalimat;): konversi dari std::string ke view terjadi otomatis; v hanya mencatat alamat dan panjang kalimat. Karena itu angka sizeof pada dua baris terakhir menunjukkan view setengah ukuran std::string (16 versus 32 byte di platform ini; angka pasti bisa berbeda antar pustaka standar, tetapi view selalu lebih ramping).
  3. Baris 19-21 (literal langsung): memanggil hitungKata("satu dua tiga empat") tidak menyalin literal; view menunjuk langsung ke memori konstan tempat literal berada.
  4. Baris 24-25 (v.substr(8, 3)): pada std::string, substr menyalin potongan ke string baru. Pada view, substr hanya menggeser alamat awal dan memperpendek panjang — inilah sebabnya kita menyebutnya “menggeser jendela”.
  5. Baris 28-31 (remove_prefix / remove_suffix): memangkas jendela dari ujung depan atau belakang, juga tanpa salinan. Hasil tengah adalah "cpp itu" — data aslinya tidak pernah disentuh.

Bahaya: View ke Teks yang Sudah Tidak Hidup #

Karena view tidak memiliki datanya, keamanannya sepenuhnya bergantung pada sumber teks yang tetap hidup. Bahaya muncul ketika view menunjuk ke teks sementara yang langsung dihapus. Kode berikut bermasalah dan kita tampilkan tanpa klaim hasil eksekusi:

cpp dangling.cpp — kode BERMASALAH, jangan ditiru
#include <iostream>
#include <string>
#include <string_view>

int main() {
    // operator + membuat std::string SEMENTARA untuk hasilnya
    std::string_view v = std::string("sementara") + "!";
    std::cout << v << "\n";  // v menunjuk teks yang sudah tidak hidup
    return 0;
}

Jejak masalahnya: sisi kanan = membangun std::string sementara sebagai hasil penggabungan. v dibuat menunjuk ke teks milik sementara itu, lalu sementara tersebut dihapus compiler di akhir pernyataan — tepat sebelum v sempat dipakai. Mulai baris std::cout, view menjadi dangling view: menunjuk ke memori yang sudah dikembalikan. Programnya mungkin tercetak “normal” pada satu percobaan, tercetak sampah pada percobaan lain, atau gagal total — persis karakter undefined behavior yang kita bahas pada Chapter Mengakses Elemen Array.

Bentuk bermasalah lain yang senada: mengembalikan string_view yang dibuat dari std::string lokal di dalam fungsi. Saat fungsi selesai, string lokalnya ikut hilang, dan view yang dikembalikan menggantung. Aturan amannya satu kalimat: view boleh dibuat dari data yang masa hidupnya lebih panjang dari view itu sendiri — misalnya variabel std::string yang masih hidup di fungsi pemanggil, string literal, atau buffer milik program yang tahan lama.

Kapan Memakai string_view #

Gunakan string_view ketika fungsi hanya membaca teks dan tidak perlu menyimpannya melebihi durasi pemanggilan: menghitung, membandingkan, mencari, memformat. Jadikan std::string ketika fungsi perlu menyimpan atau mengubah teks. Dengan dua alat ini, konvensi parameter teks kita menjadi tegas: std::string_view untuk pembaca, std::string untuk pemilik. Peran serupa — pembaca tanpa kepemilikan — juga dipegang std::span untuk array dan std::vector, yang sudah kita lihat pada Chapter Array sebagai Parameter Fungsi; keduanya nanti bersua di Section Standard Library.

Satu catatan tambahan yang sering terlupa: view hanya membaca — tidak ada cara mengubah karakter lewat view, dan tidak ada jaminan view menunjuk ke teks berakhir '\0', sehingga view tidak boleh langsung diberikan ke API C yang menuntut const char* (gunakan .data() hanya bila sumbernya memang std::string yang menjamin penutup). Pemahaman ini melengkapi keputusan desain teks yang akan kita rangkum pada akhir section.

Chapter berikutnya memperkenalkan container paling ikonik di C++: std::vector, daftar yang ukurannya benar-benar dinamis.

Rujukan resmi: cppreference — std::string_view , cppreference — std::string_view::substr .