Penjajaran
Salah satu fitur tingkat rendah C++ adalah kemampuan untuk menentukan keselarasan objek yang tepat dalam memori untuk memanfaatkan arsitektur perangkat keras tertentu secara maksimum. Secara default, kompilator menyelaraskan anggota kelas dan struktur pada nilai ukuran mereka: bool
dan char
pada batas 1 byte, short
pada batas 2 byte, int
, , long
dan float
pada batas 4 byte, dan long long
, double
, dan long double
pada batas 8 byte.
Dalam kebanyakan skenario, Anda tidak perlu khawatir dengan penyelarasan karena penyelarasan default sudah optimal. Namun, dalam beberapa kasus, Anda dapat mencapai peningkatan performa yang signifikan, atau penghematan memori, dengan menentukan penyelarasan kustom untuk struktur data Anda. Sebelum Visual Studio 2015, Anda dapat menggunakan kata kunci __alignof
khusus Microsoft dan __declspec(align)
untuk menentukan perataan yang lebih besar dari default. Mulai dari Visual Studio 2015 Anda harus menggunakan kata kunci alignof
standar C++11 dan alignas
untuk portabilitas kode maksimum. Kata kunci baru bereaksi dengan cara yang sama di bawah tenda sebagai ekstensi khusus Microsoft. Dokumentasi untuk ekstensi tersebut juga berlaku untuk kata kunci baru. Untuk informasi selengkapnya, lihat alignof
Operator, Penentu, alignas
dan perataan. Standar C++ tidak menentukan perilaku pengemasan untuk penyelarasan pada batas yang lebih kecil dari default kompilator untuk platform target, sehingga Anda masih perlu menggunakan Microsoft #pragma pack
dalam hal ini.
Gunakan kelas aligned_storage untuk alokasi memori struktur data dengan perataan kustom. Kelas aligned_union adalah untuk menentukan keselarasan untuk serikat pekerja dengan konstruktor atau destruktor nontrivial.
Perataan dan alamat memori
Perataan adalah properti alamat memori, yang dinyatakan sebagai modul alamat numerik dengan kekuatan 2. Misalnya, alamat 0x0001103F modulo 4 adalah 3. Alamat tersebut dikatakan selaras dengan 4n+3, di mana 4 menunjukkan daya 2 yang dipilih. Perataan alamat tergantung pada kekuatan 2 yang dipilih. Modul alamat yang sama 8 adalah 7. Alamat dikatakan selaras dengan X jika perataannya adalah Xn+0.
CPU menjalankan instruksi yang beroperasi pada data yang disimpan dalam memori. Data diidentifikasi oleh alamatnya dalam memori. Satu datum juga memiliki ukuran. Kami menyebut datum secara alami selaras jika alamatnya selaras dengan ukurannya. Hal ini disebut misaligned sebaliknya. Misalnya, datum floating-point 8-byte secara alami selaras jika alamat yang digunakan untuk mengidentifikasinya memiliki perataan 8 byte.
Penanganan pengompilasi perataan data
Pengkompilasi mencoba membuat alokasi data dengan cara yang mencegah ketidakselarasan data.
Untuk jenis data sederhana, pengkompilasi menetapkan alamat yang merupakan kelipatan ukuran dalam byte jenis data. Misalnya, pengkompilasi menetapkan alamat ke variabel jenis long
yang merupakan kelipatan 4, mengatur 2 bit bawah alamat ke nol.
Pengkompilasi juga menyatukan struktur dengan cara yang secara alami menyelaraskan setiap elemen struktur. Pertimbangkan struktur struct x_
dalam contoh kode berikut:
struct x_
{
char a; // 1 byte
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
} bar[3];
Pengkompilasi melengkapi struktur ini untuk menegakkan keselarasan secara alami.
Contoh kode berikut menunjukkan bagaimana pengkompilasi menempatkan struktur padded dalam memori:
// Shows the actual memory layout
struct x_
{
char a; // 1 byte
char _pad0[3]; // padding to put 'b' on 4-byte boundary
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
char _pad1[1]; // padding to make sizeof(x_) multiple of 4
} bar[3];
Kedua deklarasi kembali sizeof(struct x_)
sebagai 12 byte.
Deklarasi kedua mencakup dua elemen padding:
char _pad0[3]
untuk menyelaraskanint b
anggota pada batas 4 byte.char _pad1[1]
untuk menyelaraskan elemen array strukturstruct _x bar[3];
pada batas 4 byte.
Padding menyelaraskan elemen bar[3]
dengan cara yang memungkinkan akses alami.
Contoh kode berikut menunjukkan bar[3]
tata letak array:
adr offset element
------ -------
0x0000 char a; // bar[0]
0x0001 char pad0[3];
0x0004 int b;
0x0008 short c;
0x000a char d;
0x000b char _pad1[1];
0x000c char a; // bar[1]
0x000d char _pad0[3];
0x0010 int b;
0x0014 short c;
0x0016 char d;
0x0017 char _pad1[1];
0x0018 char a; // bar[2]
0x0019 char _pad0[3];
0x001c int b;
0x0020 short c;
0x0022 char d;
0x0023 char _pad1[1];
alignof
dan alignas
Penentu alignas
adalah cara standar C++ portabel untuk menentukan perataan kustom variabel dan jenis yang ditentukan pengguna. Operator alignof
juga merupakan cara portabel standar untuk mendapatkan penyelarasan jenis atau variabel tertentu.
Contoh
Anda dapat menggunakan alignas
pada kelas, struct atau union, atau pada masing-masing anggota. Ketika beberapa alignas
penentu ditemui, pengkompilasi memilih yang memiliki nilai terbesar.
// alignas_alignof.cpp
// compile with: cl /EHsc alignas_alignof.cpp
#include <iostream>
struct alignas(16) Bar
{
int i; // 4 bytes
int n; // 4 bytes
alignas(4) char arr[3];
short s; // 2 bytes
};
int main()
{
std::cout << alignof(Bar) << std::endl; // output: 16
}
Baca juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk