Setelah header <numeric> tuntas, kita membuka kotak peralatan kecil yang paling sering dipakai lintas program C++: fungsi utilitas dari <utility> dan <algorithm>. Ukurannya pendek — sering hanya satu baris — tetapi justru karena itu mereka ada di hampir setiap file kode: std::swap untuk menukar dua nilai, std::exchange untuk mengganti nilai sambil mengambil yang lama, std::min/std::max/std::clamp untuk membatasi angka, dan std::make_pair untuk membentuk std::pair tanpa menulis tipe. Chapter ini juga memberi pratinjau std::move, yang penjelasan penuhnya menanti di Section Move Semantics dan Value Categories. Kita bahas semuanya lewat satu program utama, lalu pendalaman per fungsi.
swap, exchange, min, max, clamp dalam Satu Program #
#include <algorithm> // std::min, std::max, std::clamp
#include <iostream> // std::cout
#include <string> // std::string
#include <utility> // std::swap, std::exchange, std::pair, std::make_pair
int main() {
// std::swap: menukar isi dua objek dengan tipe yang sama
int x = 3, y = 8;
std::swap(x, y);
std::cout << "swap int : x=" << x << " y=" << y << "\n";
std::string s1 = "asal", s2 = "tujuan";
std::swap(s1, s2);
std::cout << "swap string : s1=" << s1 << " s2=" << s2 << "\n";
// std::exchange: ganti nilai, kembalikan nilai lama
int level = 5;
int lama = std::exchange(level, 10);
std::cout << "exchange : lama=" << lama << " baru=" << level << "\n";
// min, max, dan clamp dari <algorithm>
std::cout << "min(7, 2) : " << std::min(7, 2) << "\n";
std::cout << "max(7, 2) : " << std::max(7, 2) << "\n";
std::cout << "min daftar : " << std::min({5, 1, 9, 3}) << "\n";
std::cout << "max daftar : " << std::max({5, 1, 9, 3}) << "\n";
std::cout << "clamp(150) : " << std::clamp(150, 0, 100) << "\n";
std::cout << "clamp(85) : " << std::clamp(85, 0, 100) << "\n";
std::cout << "clamp(-12) : " << std::clamp(-12, 0, 100) << "\n";
// helper pair: make_pair menduga tipe otomatis
auto produk = std::make_pair(std::string("kopi"), 18000);
std::cout << "make_pair : " << produk.first << " " << produk.second << "\n";
// swap juga bekerja pada pair: keduanya anggota bertukar sekaligus
std::pair<int, int> p1 = {1, 2}, p2 = {30, 40};
std::swap(p1, p2);
std::cout << "swap pair : p1={" << p1.first << "," << p1.second
<< "} p2={" << p2.first << "," << p2.second << "}\n";
return 0;
}Output yang Dihasilkan:
swap int : x=8 y=3
swap string : s1=tujuan s2=asal
exchange : lama=5 baru=10
min(7, 2) : 2
max(7, 2) : 7
min daftar : 1
max daftar : 9
clamp(150) : 100
clamp(85) : 85
clamp(-12) : 0
make_pair : kopi 18000
swap pair : p1={30,40} p2={1,2}Bedah baris demi baris:
- Baris 8-10 (
std::swap(x, y)): isixdanybertukar —xmenjadi8,ymenjadi3. Untukstd::stringdi baris 12-14, swap tidak menyalin karakter: kedua string hanya bertukar isi internalnya, sehingga harganya tetap murah seberapa panjang pun teksnya. - Baris 17-18 (
std::exchange(level, 10)): fungsi ini melakukan dua hal sekaligus — mengisileveldengan10dan mengembalikan nilai lamanya,5. Variabellamamenangkap nilai lama itu. - Baris 22-23 (
std::min,std::max): masing-masing mengembalikan nilai terkecil dan terbesar dari dua argumen. Untuk lebih dari dua nilai, versi dengan daftar kurawal (baris 24-25) memilih dari sekumpulan angka sekaligus. - Baris 26-28 (
std::clamp(v, lo, hi)): menjepitvagar tetap dalam rentang[lo, hi]—150terpotong menjadi100,-12terangkat menjadi0, dan85di tengah rentang tidak tersentuh. - Baris 31-32 (
std::make_pair): tipe pasangan diduga otomatis dari argumennya, sehingga cukupautodi sisi kiri — tanpa menulisstd::pair<std::string, int>secara eksplisit. - Baris 35-37 (swap pada pair): fungsi generik seperti swap bekerja pada apa pun yang punya tukar-diri, termasuk
std::pair— kedua anggota p1 dan p2 bertukar utuh sekaligus.
min, max, dan clamp #
Ketiga fungsi ini mengembalikan referensi ke argumen yang menang, bukan salinan — detail yang membuatnya efisien untuk tipe besar seperti std::string. Ada satu aturan pemisah nilai sama yang jarang diketahui: bila kedua argumen sama, std::min mengembalikan argumen pertama dan std::max mengembalikan argumen kedua. Untuk kebutuhan mengembalikan dua nilai terkecil/terbesar sekaligus, <algorithm> menyediakan std::minmax yang membungkusnya dalam pasangan.
std::clamp(v, lo, hi) sangat praktis untuk validasi rentang: alih-alih menolak input di luar batas, kita menjepitnya kembali ke batas terdekat. Persentase yang masuk sebagai 150 menjadi 100, volume yang dihitung -5 menjadi 0. Satu syarat yang perlu dijaga: argumen lo tidak boleh lebih besar dari hi, karena hasilnya tidak terdefinisi bila urutannya terbalik.
std::exchange dan Pratinjau std::move #
std::exchange(a, baru) adalah cara satu baris untuk “ambil nilai lama, pasang nilai baru”. Pemakaian paling terkenal ada di move constructor — constructor yang mengambil isi objek lain alih-alih menyalinnya. Program berikut adalah pratinjau kecilnya:
#include <iostream> // std::cout
#include <string> // std::string
#include <utility> // std::exchange, std::move
class Berkas {
public:
explicit Berkas(std::string isi) : isi_(std::move(isi)) {}
// pratinjau move constructor: ambil isi objek lain, kosongkan miliknya
Berkas(Berkas&& lain) noexcept
: isi_(std::exchange(lain.isi_, {})) {}
const std::string& isi() const { return isi_; }
private:
std::string isi_;
};
int main() {
Berkas sumber("data penting");
Berkas tujuan(std::move(sumber)); // pindahkan isi, bukan salin
std::cout << "tujuan : " << tujuan.isi() << "\n";
std::cout << "sumber : \"" << sumber.isi() << "\" (dikosongkan)\n";
return 0;
}Output yang Dihasilkan:
tujuan : data penting
sumber : "" (dikosongkan)- Baris 10-11 (
Berkas(Berkas&& lain)): parameterBerkas&&disebut rvalue reference — referensi yang menunjuk objek yang isinya boleh dipindahkan. Konsep lengkapnya dibahas tuntas pada Section Move Semantics dan Value Categories; untuk saat ini cukup pahami idiom baris berikutnya. - Baris 11 (
std::exchange(lain.isi_, {})): inilah idiom andalannya — dalam satu ekspresi, isilain.isi_(teks"data penting") pindah menjadi nilai awal anggotaisi_milik objek baru, danlain.isi_diganti dengan string kosong. Tidak ada penyalinan karakter, tidak ada baris yang terlewat. - Baris 21 (
std::move(sumber)):std::movetidak memindahkan apa pun; ia hanya menandaisumbersebagai “boleh dipindahkan”, sehingga compiler memilih move constructor di atas. Setelah baris ini, isisumbersecara terkendali menjadi kosong. - Baris 23-24 (hasil):
tujuanmemegang teks utuh,sumbertercetak kosong — pemindahan selesai tanpa satu karakter pun disalin.
Helper untuk std::pair #
<utility> juga menjadi rumah std::pair beserta pembantunya. std::make_pair(a, b) membentuk pasangan sambil menduga tipenya otomatis — berbeda dengan menulis std::pair<std::string, int> yang menduplikasi informasi yang sudah terlihat dari argumen. Fungsi generik yang sudah kita bahas turut bekerja di sini: std::swap menukar utuh dua pasangan, dan std::min/std::max membandingkan pasangan berdasarkan anggota pertama lalu kedua.
Kumpulan fungsi kecil ini menutup bekal satu per satu: kita kini bisa menukar, mengganti, menjepit, dan membentuk pasangan dengan panggilan pustaka yang idiomatik. Chapter berikutnya adalah penutup Section Standard Library: kita menyusun keputusan — container apa yang tepat untuk tiap kebutuhan dari seluruh container yang sudah kita pelajari.
Rujukan resmi: cppreference — std::swap , cppreference — std::exchange , cppreference — std::clamp .