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.
Bir başlatıcı bir değişkenin başlangıç değerini belirtir. Değişkenleri şu bağlamlarda başlatabilirsiniz:
Bir değişkenin tanımı içinde:
int i = 3; Point p1{ 1, 2 };
Bir işlevin parametrelerinden biri olarak:
set_point(Point{ 5, 6 });
Bir işlevin dönüş değeri olarak:
Point get_new_point(int x, int y) { return { x, y }; } Point get_new_point(int x, int y) { return Point{ x, y }; }
Başlatıcılar şu biçimleri alabilir:
Parantez içinde bir ifade (veya virgülle ayrılmış ifadeler listesi):
Point p1(1, 2);
Ardından bir ifade gelen bir eşittir işareti:
string s = "hello";
Bir küme ayracıyla belirtilen başlatıcı listesi. Liste, aşağıdaki örnekte olduğu gibi boş olabilir veya bir liste kümesinden oluşabilir:
struct Point{ int x; int y; }; class PointConsumer{ public: void set_point(Point p){}; void set_points(initializer_list<Point> my_list){}; }; int main() { PointConsumer pc{}; pc.set_point({}); pc.set_point({ 3, 4 }); pc.set_points({ { 3, 4 }, { 5, 6 } }); }
Başlatma türleri
Program yürütmesinde farklı noktalarda gerçekleşebilecek çeşitli başlatma türleri vardır. Farklı başlatma türleri birbirini dışlamaz; örneğin, liste başlatma değer başlatmayı tetikleyebilir ve diğer durumlarda toplu başlatmayı tetikleyebilir.
Sıfır başlatma
Sıfır başlatma, sıfır değerindeki bir değişken ayarının örtülü olarak şu türe dönüştürülmesidir:
Sayısal değişkenler 0 olarak başlatılır (ya da 0.0 ya da 0.0000000000 vb.).
Char değişkenleri olarak
'\0'
başlatılır.İşaretçiler olarak
nullptr
başlatılır.Diziler, POD sınıfları, yapılar ve birleşimler, üyelerinin sıfır değere başlatılmasını sağlar.
Farklı zamanlarda sıfır başlatma gerçekleştirilir:
Program başlangıcında, statik süresi olan tüm adlandırılmış değişkenler için. Bu değişkenler daha sonra yeniden başlatılmış olabilir.
Değer başlatma sırasında, boş ayraçlar kullanılarak başlatılan skalar türler ve POD sınıf türleri için.
Yalnızca üyelerinin başlattığu bir alt kümesi bulunan diziler.
Sıfır başlatma için bazı örnekler şunlardır:
struct my_struct{
int i;
char c;
};
int i0; // zero-initialized to 0
int main() {
static float f1; // zero-initialized to 0.000000000
double d{}; // zero-initialized to 0.00000000000000000
int* ptr{}; // initialized to nullptr
char s_array[3]{'a', 'b'}; // the third char is initialized to '\0'
int int_array[5] = { 8, 9, 10 }; // the fourth and fifth ints are initialized to 0
my_struct a_struct{}; // i = 0, c = '\0'
}
Varsayılan başlatma
Sınıflar, yapılar ve birleşimler için varsayılan başlatma, varsayılan oluşturucuyla başlatılır. Varsayılan oluşturucu başlatma ifadesi olmadan veya anahtar sözcüğüyle new
çağrılabilir:
MyClass mc1;
MyClass* mc3 = new MyClass;
Sınıf, yapı veya birleşim varsayılan bir oluşturucuya sahip değilse, derleyici bir hata yayar.
Skaler değişkenler, başlatma ifadesi olmadan tanımlandığında varsayılan olarak başlatılır. Belirsiz değerlere sahiptirler.
int i1;
float f;
char c;
Diziler, başlatma ifadesi olmadan tanımlandığında varsayılan olarak başlatılır. Bir dizi varsayılan olarak başlatıldığında, üyeleri varsayılan olarak başlatılır ve aşağıdaki örnekte olduğu gibi belirsiz değerlere sahiptir:
int int_arr[3];
Dizi üyeleri varsayılan bir oluşturucuya sahip değilse, derleyici bir hata yayar.
Sabit değişkenlerin varsayılan olarak başlatılması
Sabit değişkenlerin bir başlatıcı ile birlikte bildirilmesi gerekir. Skaler türlerse derleyici hatasına neden olurlar ve varsayılan oluşturucuya sahip sınıf türleriyse uyarıya neden olurlar:
class MyClass{};
int main() {
//const int i2; // compiler error C2734: const object must be initialized if not extern
//const char c2; // same error
const MyClass mc1; // compiler error C4269: 'const automatic data initialized with compiler generated default constructor produces unreliable results
}
Statik değişkenlerin varsayılan başlatması
Başlatıcı olmadan bildirilen statik değişkenler 0'a başlatılır (örtük olarak türüne dönüştürülür).
class MyClass {
private:
int m_int;
char m_char;
};
int main() {
static int int1; // 0
static char char1; // '\0'
static bool bool1; // false
static MyClass mc1; // {0, '\0'}
}
Genel statik nesnelerin başlatılması hakkında daha fazla bilgi için bkz . ana işlev ve komut satırı bağımsız değişkenleri.
Değer başlatma
Değer başlatma aşağıdaki durumlarda gerçekleşir:
Adlandırılmış bir değer boş küme ayracı başlatması kullanılarak başlatılır
Anonim geçici nesne boş ayraçlar veya ayraçlar kullanılarak başlatılır
bir nesne anahtar sözcüğü ve
new
boş ayraçlar veya ayraçlarla başlatılır
Değer başlatma aşağıdakileri yapar:
En az bir ortak oluşturucuya sahip sınıflar için varsayılan oluşturucu çağrılır
bildirilmemiş oluşturucuları olmayan nonunion sınıfları için nesne sıfır başlatılır ve varsayılan oluşturucu çağrılır
diziler için her öğe değer olarak başlatılır
diğer tüm durumlarda değişken sıfır başlatılır
class BaseClass {
private:
int m_int;
};
int main() {
BaseClass bc{}; // class is initialized
BaseClass* bc2 = new BaseClass(); // class is initialized, m_int value is 0
int int_arr[3]{}; // value of all members is 0
int a{}; // value of a is 0
double b{}; // value of b is 0.00000000000000000
}
Kopyalama başlatma
Kopyalama başlatma, bir nesnenin farklı bir nesne kullanılarak başlatılmasıdır. Aşağıdaki durumlarda oluşur:
bir değişken eşittir işareti kullanılarak başlatılır
bir işleve bağımsız değişken geçirilir
bir işlevden bir nesne döndürülür
özel durum oluştu veya yakalandı
Statik olmayan bir veri üyesi eşittir işareti kullanılarak başlatılır
sınıf, yapı ve birleşim üyeleri, toplama başlatma sırasında kopya başlatma ile başlatılır. Örnekler için bkz . Toplu başlatma .
Aşağıdaki kod, kopyalama başlatmanın çeşitli örneklerini gösterir:
#include <iostream>
using namespace std;
class MyClass{
public:
MyClass(int myInt) {}
void set_int(int myInt) { m_int = myInt; }
int get_int() const { return m_int; }
private:
int m_int = 7; // copy initialization of m_int
};
class MyException : public exception{};
int main() {
int i = 5; // copy initialization of i
MyClass mc1{ i };
MyClass mc2 = mc1; // copy initialization of mc2 from mc1
MyClass mc1.set_int(i); // copy initialization of parameter from i
int i2 = mc2.get_int(); // copy initialization of i2 from return value of get_int()
try{
throw MyException();
}
catch (MyException ex){ // copy initialization of ex
cout << ex.what();
}
}
Kopyalama başlatma açık oluşturucuları çağıramaz.
vector<int> v = 10; // the constructor is explicit; compiler error C2440: can't convert from 'int' to 'std::vector<int,std::allocator<_Ty>>'
regex r = "a.*b"; // the constructor is explicit; same error
shared_ptr<int> sp = new int(1729); // the constructor is explicit; same error
Bazı durumlarda, sınıfın kopya oluşturucusu silinmişse veya erişilemezse, kopya başlatma bir derleyici hatasına neden olur.
Doğrudan başlatma
Doğrudan başlatma, (boş olmayan) ayraçlar veya parantezler kullanılarak başlatılıyor. Kopya başlatmanın aksine açık oluşturucuları çağırabilir: Aşağıdaki durumlarda oluşur:
bir değişken boş olmayan ayraçlar veya ayraçlarla başlatılır
bir değişken anahtar sözcüğü ve
new
boş olmayan ayraçlar veya ayraçlarla başlatılırile bir değişken başlatılır
static_cast
oluşturucuda temel sınıflar ve statik olmayan üyeler başlatıcı listesiyle başlatılır
bir lambda ifadesinin içinde yakalanan değişkenin kopyasında
Aşağıdaki kod, doğrudan başlatmanın bazı örneklerini gösterir:
class BaseClass{
public:
BaseClass(int n) :m_int(n){} // m_int is direct initialized
private:
int m_int;
};
class DerivedClass : public BaseClass{
public:
// BaseClass and m_char are direct initialized
DerivedClass(int n, char c) : BaseClass(n), m_char(c) {}
private:
char m_char;
};
int main(){
BaseClass bc1(5);
DerivedClass dc1{ 1, 'c' };
BaseClass* bc2 = new BaseClass(7);
BaseClass bc3 = static_cast<BaseClass>(dc1);
int a = 1;
function<int()> func = [a](){ return a + 1; }; // a is direct initialized
int n = func();
}
Liste başlatma
Liste başlatma, bir değişken kümeli başlatıcı listesi kullanılarak başlatıldığında gerçekleşir. Kümeli başlatıcı listeleri aşağıdaki durumlarda kullanılabilir:
bir değişken başlatıldı
anahtar sözcüğüyle
new
bir sınıf başlatılırbir işlevden bir nesne döndürülür
bir işleve geçirilen bağımsız değişken
doğrudan başlatmadaki bağımsız değişkenlerden biri
statik olmayan bir veri üyesi başlatıcısında
oluşturucu başlatıcı listesinde
Aşağıdaki kod, bazı liste başlatma örneklerini gösterir:
class MyClass {
public:
MyClass(int myInt, char myChar) {}
private:
int m_int[]{ 3 };
char m_char;
};
class MyClassConsumer{
public:
void set_class(MyClass c) {}
MyClass get_class() { return MyClass{ 0, '\0' }; }
};
struct MyStruct{
int my_int;
char my_char;
MyClass my_class;
};
int main() {
MyClass mc1{ 1, 'a' };
MyClass* mc2 = new MyClass{ 2, 'b' };
MyClass mc3 = { 3, 'c' };
MyClassConsumer mcc;
mcc.set_class(MyClass{ 3, 'c' });
mcc.set_class({ 4, 'd' });
MyStruct ms1{ 1, 'a', { 2, 'b' } };
}
Toplu başlatma
Toplama başlatma diziler veya sınıf türleri için (çoğunlukla yapılar veya birlikler) şunlara sahip olan bir liste başlatma biçimidir:
özel veya korumalı üye yok
açıkça varsayılan veya silinmiş oluşturucular dışında kullanıcı tarafından sağlanan oluşturucular yok
temel sınıf yok
sanal üye işlevi yok
Not
Visual Studio 2015 ve önceki sürümlerinde, statik olmayan üyeler için küme ayracı veya eşit başlatıcılara sahip bir toplamaya izin verilmez. Bu kısıtlama C++14 standardında kaldırıldı ve Visual Studio 2017'de uygulandı.Toplama başlatıcıları, aşağıdaki örnekte olduğu gibi eşittir işareti olan veya olmayan bir kümeli başlatma listesinden oluşur:
#include <iostream>
using namespace std;
struct MyAggregate{
int myInt;
char myChar;
};
struct MyAggregate2{
int myInt;
char myChar = 'Z'; // member-initializer OK in C++14
};
int main() {
MyAggregate agg1{ 1, 'c' };
MyAggregate2 agg2{2};
cout << "agg1: " << agg1.myChar << ": " << agg1.myInt << endl;
cout << "agg2: " << agg2.myChar << ": " << agg2.myInt << endl;
int myArr1[]{ 1, 2, 3, 4 };
int myArr2[3] = { 5, 6, 7 };
int myArr3[5] = { 8, 9, 10 };
cout << "myArr1: ";
for (int i : myArr1){
cout << i << " ";
}
cout << endl;
cout << "myArr3: ";
for (auto const &i : myArr3) {
cout << i << " ";
}
cout << endl;
}
Aşağıdaki çıkışı görmeniz gerekir:
agg1: c: 1
agg2: Z: 2
myArr1: 1 2 3 4
myArr3: 8 9 10 0 0
Önemli
Yukarıda gösterildiği gibi myArr3
, toplu başlatma sırasında açıkça başlatılmayan ancak bildirilen dizi üyeleri sıfır başlatılır.
Birleşimleri ve yapıları başlatma
Bir birleşim oluşturucuya sahip değilse, bunu tek bir değerle (veya birleşimin başka bir örneğiyle) başlatabilirsiniz. Değer, ilk statik olmayan alanı başlatmak için kullanılır. Bu, içinde ilk alanı başlatmak için kullanılan ilk değerin, ikinci alanı başlatmak için ikincinin vb. bulunduğu yapı başlatmadan farklıdır. Birleşimlerin ve yapıların başlatılmasını aşağıdaki örnekte karşılaştırın:
struct MyStruct {
int myInt;
char myChar;
};
union MyUnion {
int my_int;
char my_char;
bool my_bool;
MyStruct my_struct;
};
int main() {
MyUnion mu1{ 'a' }; // my_int = 97, my_char = 'a', my_bool = true, {myInt = 97, myChar = '\0'}
MyUnion mu2{ 1 }; // my_int = 1, my_char = 'x1', my_bool = true, {myInt = 1, myChar = '\0'}
MyUnion mu3{}; // my_int = 0, my_char = '\0', my_bool = false, {myInt = 0, myChar = '\0'}
MyUnion mu4 = mu3; // my_int = 0, my_char = '\0', my_bool = false, {myInt = 0, myChar = '\0'}
//MyUnion mu5{ 1, 'a', true }; // compiler error: C2078: too many initializers
//MyUnion mu6 = 'a'; // compiler error: C2440: cannot convert from 'char' to 'MyUnion'
//MyUnion mu7 = 1; // compiler error: C2440: cannot convert from 'int' to 'MyUnion'
MyStruct ms1{ 'a' }; // myInt = 97, myChar = '\0'
MyStruct ms2{ 1 }; // myInt = 1, myChar = '\0'
MyStruct ms3{}; // myInt = 0, myChar = '\0'
MyStruct ms4{1, 'a'}; // myInt = 1, myChar = 'a'
MyStruct ms5 = { 2, 'b' }; // myInt = 2, myChar = 'b'
}
Toplamalar içeren toplamaları başlatma
Toplama türleri dizi dizileri, yapı dizileri vb. gibi diğer toplama türlerini içerebilir. Bu türler iç içe küme ayraçları kullanılarak başlatılır, örneğin:
struct MyStruct {
int myInt;
char myChar;
};
int main() {
int intArr1[2][2]{{ 1, 2 }, { 3, 4 }};
int intArr3[2][2] = {1, 2, 3, 4};
MyStruct structArr[]{ { 1, 'a' }, { 2, 'b' }, {3, 'c'} };
}
Başvuru başlatma
Başvuru türü değişkenleri, başvuru türünün türetildiği türdeki bir nesneyle veya başvuru türünün türetildiği türe dönüştürülebilen bir tür nesnesiyle başlatılmalıdır. Örneğin:
// initializing_references.cpp
int iVar;
long lVar;
int main()
{
long& LongRef1 = lVar; // No conversion required.
long& LongRef2 = iVar; // Error C2440
const long& LongRef3 = iVar; // OK
LongRef1 = 23L; // Change lVar through a reference.
LongRef2 = 11L; // Change iVar through a reference.
LongRef3 = 11L; // Error C3892
}
Geçici bir nesneyle başvuru başlatmanın tek yolu, sabit bir geçici nesne başlatmaktır. Bir başvuru türü değişkeni başlatıldıktan sonra her zaman aynı nesneyi gösterir; başka bir nesneye işaret etmek için değiştirilemez.
Söz dizimi aynı olsa da, başvuru türü değişkenlerin başlatılması ve başvuru türü değişkenlere atamanın ad farkı vardır. Yukarıdaki örnekte, değişen ve lVar
başlatmalara iVar
benzeyen ancak farklı etkileri olan atamalar. Başlatma, başvuru türü değişkeninin işaret ettiği nesneyi belirtir; atama, başvuru aracılığıyla başvuruda bulunılan nesneye atar.
Hem başvuru türündeki bir bağımsız değişkeni işleve geçirme hem de bir işlevden başvuru türü değeri döndürme işlemi başlatma işlemi olduğundan, döndürülen başvurular gibi işleve yönelik resmi bağımsız değişkenler de doğru şekilde başlatılır.
Başvuru türündeki değişkenler yalnızca aşağıdaki başlatıcılar olmadan bildirilebilir:
İşlev bildirimleri (prototipler). Örneğin:
int func( int& );
İşlev dönüş türü bildirimleri. Örneğin:
int& func( int& );
Başvuru türü sınıf üyesinin bildirimi. Örneğin:
class c {public: int& i;};
açıkça olarak
extern
belirtilen bir değişkenin bildirimi. Örneğin:extern int& iVal;
Bir başvuru türü değişkeni başlatılırken, derleyici bir nesneye başvuru oluşturmak veya başvurunun işaret ettiği geçici bir nesne oluşturmak arasında seçim yapmak için aşağıdaki şekilde gösterilen karar grafını kullanır:
Karar grafı şununla başlar: başlatıcı aynı türde bir lvalue mu yoksa başvuru türünden türetilmiş bir tür mü? Evet ise, başvuru başlatıcıda belirtilen nesneye başvurur. Hayır ise, bir sonraki karar başvuru türü değişkeninin başlatılmakta olan bir const T başvurusu olup olmadığıdır ve başlatıcı örtük olarak T'ye dönüştürülebilir mi? Evet ise, geçici oluşturulur ve başvuru değişkeni bu geçici için bir ad olur. Hayır ise, bu bir hatadır.
Başvuru türlerinin başlatılması için karar grafı
Tür başvuruları volatile
(typename&identifier olarak volatile
bildirilmiştir) aynı türdeki nesnelerle volatile
veya olarak volatile
bildirilmemiş nesnelerle başlatılabilir. Ancak, bu tür nesnelerle const
başlatılamazlar. Benzer şekilde, tür başvuruları const
(typename&identifier olarak const
bildirilmiştir) aynı türdeki nesnelerle const
(veya bu türe dönüştürmesi olan veya olarak const
bildirilmemiş nesnelerle) başlatılabilir. Ancak, bu tür nesnelerle volatile
başlatılamazlar.
veya volatile
anahtar sözcüğüyle nitelenmemiş başvurular yalnızca ne ne de volatile
const
const
olarak bildirilen nesnelerle başlatılabilir.
Dış değişkenleri başlatma
Otomatik, statik ve dış değişkenlerin bildirimleri başlatıcılar içerebilir. Ancak, dış değişkenlerin bildirimleri yalnızca değişkenler olarak extern
bildirilmeyen başlatıcılar içerebilir.