Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Dizi, belleğin bitişik bir alanını kaplayan aynı türdeki nesnelerin dizisidir. Geleneksel C stili diziler birçok hatanın kaynağıdır, ancak özellikle eski kod tabanlarında hala yaygındır. Modern C++'da, bu bölümde açıklanan C stili diziler yerine veya std::vector
kullanılmasını std::array
kesinlikle öneririz. Bu standart kitaplık türlerinin her ikisi de öğelerini bitişik bir bellek bloğu olarak depolar. Ancak, daha fazla tür güvenliği sağlar ve dizi içinde geçerli bir konuma işaret etme garantisi olan yineleyicileri destekler. Daha fazla bilgi için bkz . Kapsayıcılar.
Yığın bildirimleri
C++ dizi bildiriminde, dizi boyutu diğer bazı dillerde olduğu gibi tür adından sonra değil değişken adından sonra belirtilir. Aşağıdaki örnek, yığında ayrılacak 1000 çiftlik bir dizi bildirir. Öğe sayısı tamsayı değişmez değeri olarak veya sabit ifade olarak sağlanmalıdır. Bunun nedeni derleyicinin ne kadar yığın alanı ayıracaklarını bilmesidir; çalışma zamanında hesaplanan bir değeri kullanamaz. Dizideki her öğeye 0 varsayılan değeri atanır. Varsayılan bir değer atamazsanız, her öğe başlangıçta bu bellek konumundaki rastgele değerleri içerir.
constexpr size_t size = 1000;
// Declare an array of doubles to be allocated on the stack
double numbers[size] {0};
// Assign a new value to the first element
numbers[0] = 1;
// Assign a value to each subsequent element
// (numbers[1] is the second element in the array.)
for (size_t i = 1; i < size; i++)
{
numbers[i] = numbers[i-1] * 1.1;
}
// Access each element
for (size_t i = 0; i < size; i++)
{
std::cout << numbers[i] << " ";
}
Dizideki ilk öğe sıfırıncı öğedir. Son öğe (n-1) öğesidir; burada n , dizinin içerebileceği öğelerin sayısıdır. Bildirimdeki öğelerin sayısı tam sayı türünde olmalı ve 0'dan büyük olmalıdır. Programınızın alt simge işlecine değerinden (size - 1)
büyük bir değer geçirmediğinden emin olmak sizin sorumluluğunuzdadır.
Sıfır boyutlu bir dizi yalnızca dizi veya struct
union
içindeki son alan olduğunda ve Microsoft uzantıları etkinleştirildiğinde (/Za
veya /permissive-
ayarlı olmadığında) yasaldır.
Yığın tabanlı dizilerin ayrılması ve erişimi yığın tabanlı dizilere göre daha hızlıdır. Ancak yığın alanı sınırlıdır. Dizi öğelerinin sayısı çok fazla yığın belleği kullanacağı kadar büyük olamaz. Ne kadarın çok fazla olduğu programınıza bağlıdır. Bir dizinin çok büyük olup olmadığını belirlemek için profil oluşturma araçlarını kullanabilirsiniz.
Yığın bildirimleri
Yığında ayrılamayacak kadar büyük veya derleme zamanında boyutu bilinmeyen bir diziye ihtiyacınız olabilir. Bir ifade kullanarak new[]
yığında bu diziyi ayırmak mümkündür. işleci, ilk öğeye bir işaretçi döndürür. Alt simge işleci, işaretçi değişkeni üzerinde yığın tabanlı dizide çalıştığı gibi çalışır. İşaretçiyi dizideki herhangi bir rastgele öğeye taşımak için işaretçi aritmetiği de kullanabilirsiniz. Şu güvenceyi vermek sizin sorumluluğunuzdadır:
- artık diziye ihtiyacınız kalmadığında belleği silebilmeniz için her zaman özgün işaretçi adresinin bir kopyasını saklarsınız.
- işaretçi adresini dizi sınırlarının dışına artırmaz veya azaltmazsınız.
Aşağıdaki örnekte, çalışma zamanında yığında bir dizinin nasıl tanımlanacağı gösterilmektedir. Alt indis işlecini kullanarak ve işaretçi aritmetiği kullanarak dizi öğelerine nasıl erişeceklerini gösterir:
void do_something(size_t size)
{
// Declare an array of doubles to be allocated on the heap
double* numbers = new double[size]{ 0 };
// Assign a new value to the first element
numbers[0] = 1;
// Assign a value to each subsequent element
// (numbers[1] is the second element in the array.)
for (size_t i = 1; i < size; i++)
{
numbers[i] = numbers[i - 1] * 1.1;
}
// Access each element with subscript operator
for (size_t i = 0; i < size; i++)
{
std::cout << numbers[i] << " ";
}
// Access each element with pointer arithmetic
// Use a copy of the pointer for iterating
double* p = numbers;
for (size_t i = 0; i < size; i++)
{
// Dereference the pointer, then increment it
std::cout << *p++ << " ";
}
// Alternate method:
// Reset p to numbers[0]:
p = numbers;
// Use address of pointer to compute bounds.
// The compiler computes size as the number
// of elements * (bytes per element).
while (p < (numbers + size))
{
// Dereference the pointer, then increment it
std::cout << *p++ << " ";
}
delete[] numbers; // don't forget to do this!
}
int main()
{
do_something(108);
}
Dizileri başlatma
Bir diziyi bir döngüde, bir kerede bir öğede veya tek bir deyimde başlatabilirsiniz. Aşağıdaki iki dizinin içeriği aynıdır:
int a[10];
for (int i = 0; i < 10; ++i)
{
a[i] = i + 1;
}
int b[10]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
dizileri işlevlere geçirme
Bir dizi bir işleve geçirildiğinde, yığın tabanlı veya yığın tabanlı bir dizi olsun, ilk öğeye işaretçi olarak geçirilir. İşaretçi başka boyut veya tür bilgisi içermiyor. Bu davranışa işaretçi bozulması denir. Bir diziyi bir işleve geçirirken, her zaman ayrı bir parametredeki öğe sayısını belirtmeniz gerekir. Bu davranış, dizi bir işleve geçirildiğinde dizi öğelerinin kopyalanmayan anlamına da gelir. İşlevin öğeleri değiştirmesini önlemek için parametresini öğelere const
işaretçi olarak belirtin.
Aşağıdaki örnekte bir dizi ve uzunluk kabul eden bir işlev gösterilmektedir. İşaretçi, kopyayı değil özgün diziyi işaret eder. parametresi olmadığından const
işlev dizi öğelerini değiştirebilir.
void process(double *p, const size_t len)
{
std::cout << "process:\n";
for (size_t i = 0; i < len; ++i)
{
// do something with p[i]
}
}
dizi parametresini p
işlev bloğu içinde salt okunur yapmak için olarak const
bildirin ve tanımlayın:
void process(const double *p, const size_t len);
Aynı işlev, davranış değişikliği olmadan bu yollarla da bildirilebilir. Dizi hala ilk öğeye bir işaretçi olarak geçirilir:
// Unsized array
void process(const double p[], const size_t len);
// Fixed-size array. Length must still be specified explicitly.
void process(const double p[1000], const size_t len);
Çok boyutlu diziler
Diğer dizilerden yapılan diziler çok boyutlu dizilerdir. Bu çok boyutlu diziler, sıralanmış birden çok köşeli ayraçlı sabit ifade yerleştirilerek belirtilir. Örneğin, şu bildirimi göz önünde bulundurun:
int i2[5][7];
Aşağıdaki şekilde gösterildiği gibi, kavramsal olarak beş satır ve yedi sütundan oluşan iki boyutlu bir matris halinde düzenlenmiş türünde int
bir dizi belirtir:
Görüntü, 7 hücre genişliğinde ve 5 hücre yüksekliğinde bir kılavuzdur. Her hücre, hücrenin dizinini içerir. İlk hücre dizini 0,0 olarak etiketlenmiştir. Bu satırdaki sonraki hücre 0,1'dir ve bu satırdaki son hücre olan 0,6'dır. Sonraki satır 1,0 diziniyle başlar. Bundan sonraki hücrenin dizini 1,1 olur. Bu satırdaki son hücre 1,6'dır. Bu düzen, 4,0 diziniyle başlayan son satıra kadar yineler. Son satırdaki son hücrenin dizini 4,6'dır.
Başlatıcı listesi olan çok boyutlu diziler bildirebilirsiniz (Başlatıcılar'da açıklandığı gibi). Bu bildirimlerde, ilk boyut için sınırları belirten sabit ifade atlanabilir. Örneğin:
// arrays2.cpp
// compile with: /c
const int cMarkets = 4;
// Declare a float that represents the transportation costs.
double TransportCosts[][cMarkets] = {
{ 32.19, 47.29, 31.99, 19.11 },
{ 11.29, 22.49, 33.47, 17.29 },
{ 41.97, 22.09, 9.76, 22.55 }
};
Yukarıdaki bildirim, üç satıra dört sütuna sahip bir dizi tanımlar. Satırlar fabrikaları, sütunlar ise fabrikaların sevk ettiği pazarları temsil ediyor. Değerler, fabrikalardan pazarlara ulaşım maliyetleridir. Dizinin ilk boyutu dışarıda bırakılır, ancak derleyici başlatıcıyı inceleyerek bunu doldurur.
N boyutlu dizi türünde dolaylı işlecin (*) kullanılması n-1 boyutlu bir dizi verir. n 1 ise, bir skaler (veya dizi öğesi) elde edilir.
C++ dizileri birincil satır sırasına göre depolanır. Satır-ana sıra, son alt simgenin en hızlı şekilde değiştiği anlamına gelir.
Örnek
Burada gösterildiği gibi, işlev bildirimlerinde çok boyutlu bir dizinin ilk boyutu için sınır belirtimini atlayabilirsiniz:
// multidimensional_arrays.cpp
// compile with: /EHsc
// arguments: 3
#include <limits> // Includes DBL_MAX
#include <iostream>
const int cMkts = 4, cFacts = 2;
// Declare a float that represents the transportation costs
double TransportCosts[][cMkts] = {
{ 32.19, 47.29, 31.99, 19.11 },
{ 11.29, 22.49, 33.47, 17.29 },
{ 41.97, 22.09, 9.76, 22.55 }
};
// Calculate size of unspecified dimension
const int cFactories = sizeof TransportCosts /
sizeof( double[cMkts] );
double FindMinToMkt( int Mkt, double myTransportCosts[][cMkts], int mycFacts);
using namespace std;
int main( int argc, char *argv[] ) {
double MinCost;
if (argv[1] == 0) {
cout << "You must specify the number of markets." << endl;
exit(0);
}
MinCost = FindMinToMkt( *argv[1] - '0', TransportCosts, cFacts);
cout << "The minimum cost to Market " << argv[1] << " is: "
<< MinCost << "\n";
}
double FindMinToMkt(int Mkt, double myTransportCosts[][cMkts], int mycFacts) {
double MinCost = DBL_MAX;
for( size_t i = 0; i < cFacts; ++i )
MinCost = (MinCost < TransportCosts[i][Mkt]) ?
MinCost : TransportCosts[i][Mkt];
return MinCost;
}
The minimum cost to Market 3 is: 17.29
İşlev FindMinToMkt
, yeni fabrikaların eklenmesi için herhangi bir kod değişikliği gerekmeyecek şekilde yazılır, yalnızca yeniden derleme gerekir.
Dizileri Başlatma
Sınıf oluşturucuya sahip nesnelerin dizileri oluşturucu tarafından başlatılır. Başlatıcı listesinde dizideki öğelerden daha az öğe olduğunda, kalan öğeler için varsayılan oluşturucu kullanılır. Sınıf için hiçbir varsayılan oluşturucu tanımlanmamışsa, başlatıcı listesinin tamamlanmış olması, yani dizideki her öğe için bir başlatıcı olması gerekir.
İki oluşturucu tanımlayan Point
sınıfını göz önünde bulundurun:
// initializing_arrays1.cpp
class Point
{
public:
Point() // Default constructor.
{
}
Point( int, int ) // Construct from two ints
{
}
};
// An array of Point objects can be declared as follows:
Point aPoint[3] = {
Point( 3, 3 ) // Use int, int constructor.
};
int main()
{
}
İlk aPoint
öğesi Point( int, int )
oluşturucusu kullanılarak oluşturulur; kalan iki öğe varsayılan oluşturucu kullanılarak oluşturulur.
Statik üye dizileri (ister olsun ister const
olmasın), tanımlarında (sınıf bildirimi dışında) başlatılabilir. Örneğin:
// initializing_arrays2.cpp
class WindowColors
{
public:
static const char *rgszWindowPartList[7];
};
const char *WindowColors::rgszWindowPartList[7] = {
"Active Title Bar", "Inactive Title Bar", "Title Bar Text",
"Menu Bar", "Menu Bar Text", "Window Background", "Frame" };
int main()
{
}
Dizi öğelerine erişme
Dizi alt indis işlecini ([ ]
kullanarak bir dizinin tek tek öğelerine erişebilirsiniz. Alt indis olmadan tek boyutlu bir dizinin adını kullanırsanız, dizinin ilk öğesinin işaretçisi olarak değerlendirilir.
// using_arrays.cpp
int main() {
char chArray[10];
char *pch = chArray; // Evaluates to a pointer to the first element.
char ch = chArray[0]; // Evaluates to the value of the first element.
ch = chArray[3]; // Evaluates to the value of the fourth element.
}
Çok boyutlu diziler kullandığınızda, ifadelerde çeşitli birleşimler kullanabilirsiniz.
// using_arrays_2.cpp
// compile with: /EHsc /W1
#include <iostream>
using namespace std;
int main() {
double multi[4][4][3]; // Declare the array.
double (*p2multi)[3];
double (*p1multi);
cout << multi[3][2][2] << "\n"; // C4700 Use three subscripts.
p2multi = multi[3]; // Make p2multi point to
// fourth "plane" of multi.
p1multi = multi[3][2]; // Make p1multi point to
// fourth plane, third row
// of multi.
}
Yukarıdaki kodda türünde multi
üç boyutlu bir dizidir double
. İşaretçi, p2multi
üç boyutlu bir diziye double
işaret eder. Bu örnekte, dizi bir, iki ve üç alt indis ile kullanılır. Deyiminde olduğu gibi tüm alt indislerin belirtilmesi daha yaygın olsa da cout
, bazen izleyen cout
deyimlerde gösterildiği gibi dizi öğelerinin belirli bir alt kümesini seçmek yararlı olabilir.
Alt simge işlecini aşırı yükleme
Diğer işleçler gibi, alt simge işleci ([]
) kullanıcı tarafından yeniden tanımlanabilir. Alt simge işlecinin varsayılan davranışı, aşırı yüklenmemişse, aşağıdaki yöntemi kullanarak dizi adını ve alt simgeyi birleştirmektir:
*((array_name) + (subscript))
İşaretçi türlerini içeren tüm eklerde olduğu gibi, türün boyutuna göre ayarlamak için ölçeklendirme otomatik olarak yapılır. Sonuç değeri kaynağından gelen n bayt değildir; bunun array_name
. öğesidir. Bu dönüştürme hakkında daha fazla bilgi için bkz . Ekleme işleçleri.
Benzer şekilde, çok boyutlu diziler için aşağıdaki yöntem kullanılarak adres türetilir:
((array_name) + (subscript1 * max2 * max3 * ... * maxn) + (subscript2 * max3 * ... * maxn) + ... + subscriptn))
İfadelerdeki Diziler
bir dizi türünün tanımlayıcısı , adresi ()sizeof
dışında &
bir ifadede veya bir başvurunun başlatılmasında göründüğünde, ilk dizi öğesinin işaretçisine dönüştürülür. Örneğin:
char szError1[] = "Error: Disk drive not ready.";
char *psz = szError1;
psz
işaretçisi szError1
dizisinin ilk öğesine işaret eder. diziler, işaretçilerin aksine değiştirilebilir l değerleri değildir. Bu nedenle aşağıdaki atama geçersizdir:
szError1 = psz;