Skip to content

Instantly share code, notes, and snippets.

@cemtopkaya
Last active November 8, 2024 17:42
Show Gist options
  • Save cemtopkaya/29ed5bab9013819470e2603d0230cbe4 to your computer and use it in GitHub Desktop.
Save cemtopkaya/29ed5bab9013819470e2603d0230cbe4 to your computer and use it in GitHub Desktop.
C++ soruları

Sorular

Soru [beginner easy compiler linker loader]

Compiler, linker ve loader arasındaki ilişkiyi anlatınız.

Cevap

image Ref: https://www.youtube.com/watch?v=m1UzSfgjA4Y&ab_channel=VijayVishwakarma


Soru [beginner easy data-segment heap-segment code-segment]

Data, heap, code/text, environment segmentlerini tanımlayınız.

Cevap

image

image

image

image

image

image

image

image

stack_c++

image

image

Ref: https://www.youtube.com/watch?v=m1UzSfgjA4Y&ab_channel=VijayVishwakarma

image

Ref: https://www.youtube.com/watch?v=_8-ht2AKyH4&ab_channel=mycodeschool


image Ref: https://www.youtube.com/watch?v=m1UzSfgjA4Y&ab_channel=VijayVishwakarma

BTK C++ Programlamaya Giriş

Soru [beginner easy]

Method ve function arasındaki fark nedir?

Cevap

Method: sınıfa bağlı fonksiyon Function: sınıfa bağlı olmayan serbest fonksiyon

Ref: https://www.btkakademi.gov.tr/portal/course/player/deliver/c-ile-programlamaya-giris-20172 (0:30)


Soru [beginner easy]

"Metodlar nesne sayısı kadar RAM'de yer alır" doğru mudur, açıklayınız?

Cevap

Nesne sayısı kadar sınıfın özellikleri vardır ancak mehod sayısı 1 olup her method çağrısında hangi nesne için bu methodun çalışacağı bilgisi geçirilir (msg2.yaz()).

image

Ref:https://www.youtube.com/watch?v=0jhQBQcGnuM&ab_channel=ThinkAloudAcademy


05 - 03/09/2022

Soru [beginner easy reference pointer]

Aşağıdaki ifadeler neyi verir?

#include <iostream>
using namespace std;

int main() {
  int x = 10;
  int *p = &x;

  // işaretçi ile x'i göstermek
  cout << *p; // ??? yazdırır
  *p = 20;
  cout << &*p;    // ??? yazar
  cout << p;      // ??? yazar
  cout << ++*p;   // ??? yazar
  cout << (*p)++; // ??? yazar

  // referans ile x'i göstermek için:
  int &r = x;
  cout << ++r; // ??? yazar
  cout << r++; // ??? yazar
  r = 30;

  // referansı işaretçi ile göstermek
  int *pr = &r;
  *pr = 40;
  cout << x; // ??
}

Cevap

int main() {
  int x = 10;
  int *p = &x;

  // işaretçi ile x'i göstermek
  cout << *p;// p, x'i gösterir. *p ise x'in değerini yani 10 yazdırır
  *p = 20;
  cout << &*p;    // *p yani x'in değerine 20 atanır
  cout << p;      // x'in adresini p işaretçisine atadığımız için x'in adresini yazar (Örn. 0x7ffc79aa896c)
  cout << ++*p;   // x'in değerini önce 1 arttırır sonra yazar (21)
  cout << (*p)++; // x'in değeri 21 olduğu için önce yazdırır sonra 1 arttırır (22) ancak yazdırmaz.

  // referans ile x'i göstermek için:
  int &r = x;
  cout << ++r; // x 22 ve r 1 arttırıldığında x'in değeri 23 olur ve yazdırır.
  cout << r++; // r'nin değeri olan 23'ü yazdırır sonra 1 arttırır.
  r = 30;

  // referansı işaretçi ile göstermek
  int *pr = &r;
  *pr = 40;
  cout << x;  // x'in değeri 40 olur
}

Soru [beginner easy declarator operator dereferencing-opertor address-of-operator]

Aşağıdaki kodda deklaratör ve operatör hangileridir?

double d = 10;
double* dptr = &d;
double& rVal = d;
*dptr++;

Cevap

double* dptr.. bildirimde kullanıldığı için * deklaratör, = &d ifadesinde & address of operatörü ve *dptr++ ifadesindeki * dereferencing operatörüdür. *dptr++ ifadesindeki *, dereferencing için kullanıldığından operatördür. double& rVal... içindeki & deklaratördür. En yaygın declarator ler:

  • * - pointer - prefix
  • *const - constant pointer - prefix
  • & - reference - prefix
  • [] - array - postfix
  • () - funtion - postfix

Soru [default-initialize easy beginner auto const reference]

Hangi varlıklar default initialize (varsayılan başlatılamaz) edilemez?

Cevap

const nesneler ve r value nesneler

  • const int x; x değeri atanmadan başlatılamaz. const nesneler default initialize ediliemez.
  • double& rvalue; referanslar default initialize edilemez
  • auto ile deklare edilen değişkenler

Soru [easy beginner reference]

Kaç referans türü vardır, söyleyiniz?

Cevap

3 referans vardır:

  • R value
  • L value
  • standartların tanımına göre forwarding reference (Scott Meyers'in tanımıyla universal reference)
int x = 10;
// aşağıdaki kodda && ile işaret edilen universal reference olur.
// hem sol taraf referansını hem doğrudan değeri yani sağ taraf referansını atayabildiğimiz için "universal reference" diğer bir adıyla "forwarding reference" diyoruz.
int&& y = x;
int&& z = 5;

Soru [easy beginner reference function-returning-pointer]

"Function returning pointer" diye çağırılan int türünde bir değeri dönen fonksiyon örneğini işaretçi ve referans dönecek şekilde 2 fonksiyonu da yazınız.

Cevap

int i = 10;

int* func_p() {
  return &i;
}

int& func_ref() {
  return i;
}

int main() {
  int* p = func_p();
  *p = 20;
  
  // ya da
  *func_p() = 30;
  
  // referans değer ile ile
  func_ref() = 20; // i'nin değerine 20 atanmış olur.
}

Soru [easy beginner reference function-returning-pointer postix-operator dereferencing-opertor]

Aşağıdaki kod çalışır mı, çıktı ne olur?

int i = 10;

int* func_p() {
  return &i;
}

int main() {
  cout << ++* func_p();
}

Cevap

önce fonksiyon operatörü (() postfix operatörlü func_p()) çalışır sonra dereferencing operatörü (*) çalışacak, en sonunda dönen değer 1 artacak ve 11 yazacaktır.


Soru [easy beginner reference]

Sol taraf referansı ile neyi amaçlarız?

Cevap

İşaretçilerde nesneye erişmek için dereferencing (*ptr) kullanıyorken bunun yerine referans değişken nesneyi doğrudan kullanabilmemizi sağlar.

int x=10;

// pointer kullanarak:
int* ptr = &x;
*ptr++ ;

// yerine aşağıdaki gibi ref kullanabiliriz:
int& ref = x;
ref++ ;

// işaretçiye bağlanmış sağ referans değişkeni şöyle okuyabiliriz:
//     "int* tipinde referans değişkeni" > int*& 
int*& refForPtr = ptr; 

// Ve işaretçiye bağlanmış referans değişkeninin değerini değiştirelim:
*refForPtr = 30;  // artık x'in değeri 30 olacaktır.

// Int türünün pointer değişkenini (yani ptr'yi) yeni bir int değişkene olan y'ye atayalım
int y = 40;
refForPtr = &y;

cout << *refForPtr << endl; // 40

Soru [easy beginner reference]

Referansları doğrudan başlatabilir miyiz?

Cevap

Değeri/nesneyi doğrudan atayamayız. Bir R value referansa ancak bir L value referansı atayabiliriz. Ancak değer/nesnenin bağlanmış olduğu bir değişkeni yani L value referansı hem atamayla hem de brace initializiation ile R value referansa bağlayabiliriz.

int x = 10;
 // 3 yöntemle de başlatabiliriz (atama, direct, brace)
 int& rVal = x;
 int& rVal(x);
 int& rVal{ x };
#include <iostream>
using namespace std;

int i = 10;

int* func_p() {
  return &i;
}

int main() {
  cout << *func_p(); // 10
  cout << func_p();  // 0x403010

  int& r = *func_p(); // int& r = i; ataması gibidir. 
  r = 12;
  cout << "r: " << r << "; i:" << i; //r: 12; i:12
}

Soru [easy beginner reference]

int x[5][10][15]{1};
 ??? = x[5][2];

??? yerine referans tür ifadesi nasıl yazılmalıdır?

Cevap

int (&r)[15] = x[5][2];


Soru [easy beginner reference nullptr]

nullptr bir nesne midir? Nesne ise nullptr yerine geçecek referans türünü yazınız.

Cevap

nullptr nesnedir ve referans ile gösterilebilir.

int* ptr = nullptr
int* &r = ptr;

ptr yerine r referansını kullanabiliriz.


Soru [easy beginner r-value reference]

Aşağıdaki kodda yapılan atamaların her satırında x ne değeri alır? Ve r = y atamasıyla r referansına y değerini bağlamış olur muyuz?

int x{3};
int& r(x);
cout << x << endl; // ?

r = 10;
cout << x << endl; // ?

++r;
cout << x << endl; // ?

int y = 20;
r = y;
cout << x << endl; // ?

Cevap

Bir referansı bağlandığı nesneden başka bir nesneye bağlamak mümkün değildir.

int x{3};
int& r(x);
cout << x << endl; // 3

r = 10;
cout << x << endl; // 10

++r;
cout << x << endl; // 11

int y = 20;
r = y;
cout << x << endl; // 20
// referanslar sadece bir kez bağlanabilir (bind) bu yüzden r değeri sadece x yerine geçer ve x'e bind edildikten sonra başka bir değere (y'ye) bağlanamaz.

Soru [easy beginner r-value reference]

Aşağıdaki kodda r2 neyi gösterir:

int x(10);
int& r1{x};
int& r2 = r1;

++r1; 
cout << x << endl; //  ?
cout << r1 << endl; // ?
cout << r2 << endl; // ?

++r2;
cout << x << endl; //  ?
cout << r1 << endl; // ?
cout << r2 << endl; // ?

Cevap

int x(10);
int& r1{x};
int& r2 = r1;
// Bir referansa atanmış referans ile ilk referansın işaret ettiği değeri (x'i) bağlamış oluruz (bind). r2 de r1 gibi x'i refere edecektir.

++r1; 
cout << x << endl; // 11
cout << r1 << endl; // 11
cout << r2 << endl; // 11

++r2;
cout << x << endl; // 12
cout << r1 << endl; // 12
cout << r2 << endl; // 12

Soru [easy beginner const pointer]

Aşağıdaki const ile neyi sağlarız?

int x = 10;
int* const p = &x;x

Cevap

p işaretçisi yaratıldığı kapsamı boyunca sadece x'i gösterir başka bir nesneyi gösteremez hale getirirlir. x'in değeri *p ile değiştirilebilir.


Soru [easy beginner c++ bit-field]

flags Türünün üyelerinin alabileceği değer aralıkları yorum satırlarında belirtilmiştir. Tanımlı haliyle flags türünden bir nesnenin kaplayacağı toplam boyutu ve flags türünü bit-field kullanarak ihtiyaca göre yer kaplayacak şekilde yazdıktan sonra üyeleri ihtiyacımıza uygun tanımladığınızdaki boyutunu yazınız.

struct Flags {
    unsigned int bayrak1; // 0..1 > 0 veya 1 değeri alır
    unsigned int bayrak2; // 0..3 > 0,1,2,3 değerlerinden birini alır
    unsigned int bayrak3; // 0..2 > 0,1,2 değerlerinden birini alır
};

Cevap

Her bir üyenin unsigned int olarak (4*3) 12 byte yer kaplar. Her üyeyi bit-field olarak tanımladığımızda toplam 4 byte yer kaplayacaktır.

struct Flags{
    unsigned int bayrak1 : 1; // 1 bit > 0..1 arasında değer alır
    unsigned int bayrak2 : 2; // 2 bit > 0,1,2,3 değerlerinden birini alır
    unsigned int bayrak3 : 2; // 2 bit > 0,1,2,3 değerlerinden birini alır
};

Soru [prgramming easy c++ bit-field]

En fazla 7 değeri alabilen, işaretsiz bir tamsayı bit-field üyesi olan bir struct tipinin tanımını yazınız.

Cevap

(cppreferans)[https://en.cppreference.com/w/cpp/language/bit_field]

struct S {
    // 3 bit uzunluğundaki b, 0...7 arasında değer alabilir
    unsigned int b : 3;
};
int main() {
    S s = {6};
 
    ++s.b; // 6 değeri 1 arttırılarak 7'ye yükselir
    std::cout << s.b << '\n'; // 7 
 
    ++s.b; // Değer 8 olmalı ancak aralık 0..7 olduğu için 0'a atanır
    std::cout << s.b << '\n'; // 0
}

Soru [prgramming easy c++ integral-promotion]

Integral promotion nedir?

Cevap

Bir karakter (char), short int veya bir integer bit-field (int a:2;), tümü işaretli olsun veya olmasın veya numaralandırma türünde bir nesne, bir tamsayının kullanılabileceği her yerde bir ifadede kullanılabilir. Bir int, orijinal türün tüm değerlerini temsil edebiliyorsa, değer int'e dönüştürülür; aksi takdirde değer unsigned int'e dönüştürülür. Bu sürece entegre promosyon (integral promotion) denir.


Soru [prgramming easy dynamic]

Dinamik ve statik tür kavramları arasındaki fark nedir?

Cevap

Dinamik türleri çalışma zamanında, statik türleri derleme zamanında kullanabiliriz. Statik tip kontrolü, derleme zamanında yapılan tip kontrolüdür. Bu, C++'ın yaptığı tek tür denetleme şeklidir. Dinamik tip kontrolü, çalışma zamanında yapılan tip kontrolüdür. Bu genellikle dinamik olarak yorumlanan dillerde görülür, ancak derlenmiş dillerde daha az yaygındır


Soru [prgramming easy dynamic-typing static-typing]

Dinamik ve statik programlama dilleri arasındaki fark nedir?

Cevap

Dinamik ve statik yazılan diller için;

  • dinamik olarak yazılan diller çalışma zamanında tip kontrolü gerçekleştirirken, statik olarak yazılan diller derleme zamanında tip kontrolü gerçekleştirir. Bu, dinamik olarak yazılan dillerde (Groovy gibi) yazılan komut dosyalarının, komut dosyasının düzgün çalışmasını (eğer varsa) önleyecek hatalar içerse bile derlenebileceği anlamına gelir. Statik olarak yazılmış bir dilde (Java gibi) yazılmış bir komut dosyası hatalar içeriyorsa, hatalar düzeltilene kadar derlenemez.
  • statik olarak yazılan diller, değişkenlerinizin veri türlerini kullanmadan önce bildirmenizi gerektirirken, dinamik olarak yazılan diller bunu yapmaz.

Soru [c++ medium intermediate auto type-deduction decltype template]

Type deduction yani "tür çıkarımı" nedir? Derleme mi çalışma zamanınında mı çalışır?

Cevap

Tamamen derleme zamanıyla ilgilidir. auto, decltype, decltype(auto), template tür çıkarım anahtarlarını kullanırız.

  • auto, bildirilen bir değişkenin türünü başlatma ifadesinden çıkarır.
  • decltype type belirtici, belirtilen bir ifadenin türünü verir. decltype tip belirleyicisi, auto anahtar sözcüğüyle birlikte, öncelikle şablon kitaplıkları yazan geliştiriciler için kullanışlıdır. Dönüş türü, şablon bağımsız değişkenlerinin türlerine bağlı olan bir işlev şablonu bildirmek için auto ve decltype kullanın. Veya, başka bir işleve yapılan çağrıyı sarmalayan ve ardından sarmalanmış işlevin dönüş türünü döndüren bir işlev şablonu bildirmek için auto ve decltype kullanın.

Soru [type-deduction auto beginner easy]

Aşağıdakilerden hangileri auto tür çıkarım anahtarının özelliklerinden değildir?

  • i) auto anahtarıyla tanımlanan değişkenler default initialize edilmez
  • ii) auto anahtarı eğer değişken, tanımlanırken değer alıyorsa kullanılır
  • iii) auto anahtarı fonksiyon parametreleri için de kullanılmaz
  • iv) auto değişkenler, yerel değişkenler gibi çalışmaktadır. Geçerli oldukları fonksiyondan veya kapsamdam (scope) çıkılınca hafızadan atılır ve yeniden geçerli oldukları kısma veya fonksiyona girildiğinde yeniden oluşturulurlar.

Cevap

auto tanımlı parametreler C++20 itibarıyla kullanılabilir. Bu yüzden iii hatalı olacaktır.


Soru [type-deduction auto beginner easy]

Aşağıdaki auto tanımlı tür çıkarım ifadelerinde auto'nun türü nedir?

  • i)
char c = 'a'; 
auto x = +c;
  • ii)
const int cx = 6;
auto y = cx;
  • iii)
int x = 10;
int& r = x;
auto y = r;
  • iv)
int x = 10;
const int& r = x;
auto y = r;
  • v)
int a[] = {1,2,3,4,5};
auto y = a;

Cevap

  • i) int türündedir çünkü char türündeki c değişkeni integral promotion ile int türüne terfi edecektir + operatörüyle.
  • ii) int türündedir çünkü cx'in türü const int olsa dahi y'nin türünde const düşecek int olacaktır
  • iii) Referans değişkenin referans olması tür çıkarımında etkili değil bu yüzden y'nin türü int olacaktır.
  • iv) const ve referans özellikleri düşer y'nin türü int olur.
  • v) int* türünde olacaktır y.

Soru [type-deduction auto beginner easy]

Aşağıdaki auto tanımlı tür çıkarım ifadelerinde auto'nun türü nedir?

  • i)
const int a[] = {1,2,3,4,5};
auto y = &a;
  • ii)
const int x = 10;
auto y = &x;
  • iii)
auto y = "isim";
  • iv)
const int x = 5;
auto y = &x;
  • v)
const int x[5]{};
auto y = x;

Cevap

  • i) const int* türünde olacaktır yani const int (*y)[5].
  • ii) y=x olduğunda değeri, y=&x olduğunda nesneyi geçirdiğimiz için const ifadesi kalacak ve const int türünde olacaktır y.
  • iii) const char* türünde olacaktır. Sağ taraf const char olacak yani const char *y = "isim" gibi tanımlanmış olacak.
  • iv) const int *y türünde olacaktır y.
  • v) const int* türünde olacaktır y.

Soru [type-deduction auto beginner easy]

  • i) auto x = 0; ifadesinde x'in türü ne olur?
  • ii) auto y = 0u; ifadesinde y'nin türü ne olur?
  • iii) auto z = 0.; ifadesinde z'nin türü ne olur?

Cevap

  • i) int
  • ii) unsigned int
  • iii) double

Soru [type-deduction auto beginner easy]

Aşağıdaki tanımlamaların hangileri doğrudur?

  • i) auto x;
  • ii) auto x{};
  • iii) auto x = ifade;

Cevap

Doğru. auto x = ifade; ile tanımlanan değişkenin türü = ifade ile belirlenir. Bu yüzden ilk değer vermek mecburidir. Yani i ve ii yanlış iii doğrudur.


Soru [reference-value pointer intermediate medium]

  • i) Aşağıdaki int a[]{1,2,3,4,5}; ifadesindeki a değişkeninin türü nedir?
  • ii) a değişkeni Sağ taraf referansı mı (R value), Sol taraf referansı (L value) mıdır?
  • iii) a değişkenin işaret eden pointer nasıl tanımlanır?
  • iv) a değişkeninin referans değişkeni nasıl tanımlanır?
  • v) Aşağıdaki ifadeler doğru mudur?
int& ra = a;
int* p1 = a <denktir?> int* p2 = &a[0] <denktir?> int* p3 = ra <denktir?> auto& ra = a

Cevap

  • i) a'nın türü: int[5]'dir.
  • ii) L value çünkü R value & declaratörü ile ifade edilir.
  • iii) int(*ptr)[5] = &a;
  • iv) int (&ra)[5] = a;
  • v) Doğrudur

Soru [type-alias typedef intermediate medium]

5 Elemanlı int dizisinin (int a[5]) tür tanımı için Type alias (tür eş adı) kullanımında aşağıdakilerden hangileri doğrudur?

  • a)
typedef int diziTipi[5];
diziTipi& rDizi = a;
  • b)
using diziTipi = int[5];
diziTipi& rDizi = a;

Cevap

Her ikisi de doğru tanımlamadır.


Soru [reference intermediate medium]

Kullanıcı tanımlı bir yapı tipinde referans kullanımına örnek veriniz.

Cevap

struct Veri {
  int a, b;
}

int main() {
  Veri v{1,2};
  cout << v.a << endl; //1
  cout << v.b << endl; //2
  
  Veri& rv = v;
  cout << rv.a << endl; //1
  rv.b = 12;
}

Soru [pointer beginner easy]

int x = 10;
int* p = &x;
  • i) *p ifadesinin türü nedir?
  • ii) p değişkeninin türü nedir?

Cevap

  • i) int
  • ii) int* (int türünde işaretçidir)

Soru [reference easy beginner]

int x = 10;
int& r = x;
  • i) r ifadesinin türü nedir?
  • ii) r değişkeninin türü nedir?

Cevap

  • i) int
  • ii) int ref (int türünde referanstır)

Soru [reference beginner easy]

Neden sol taraf değerlerini (referanslar) neden kullanırız?

Cevap

  1. Bir fonksiyona bir nesneyi call by reference olarak göndermek için
  2. Bir fonksiyon bir nesneyi kendisini çağıran fonksiyona döndürmek için

Soru [call-by-reference call-by-value easy beginner]

"Call by reference" ve "call by value" örnekleri yazınız.

Cevap

// call by value
void func_byvalue(int v){
  v = 10;
}

int main(){
  int i = 1;
  cout << i << endl; // 1
  func_byvalue(i)
  cout << i << endl; // 1
}
// call by value
void func_byref(int* p){
  *p = 10;
}

int main(){
  int i = 1;
  cout << i << endl; // 1
  func_byvalue(&i)
  cout << i << endl; // 10
}
// call by value
void func_byref(int& r){
  r = 10;
}

int main(){
  int i = 1;
  cout << i << endl; // 1
  func_byvalue(i)
  cout << i << endl; // 10
}

Soru [type-deduction auto c++ beginner easy]

auto İle yapılan tür çıkarımına (type deduction) göre türleri belirtiniz.

  • i) auto x = 5;
  • ii) auto x {5L};
  • iii) auto x (5.5);
  • iv) auto x = {5};
  • v) auto x { 5, 6 };
  • vi)
int x = 10;
auto x1 = &x;    // x1?
auto* x2 = &x;   // x2?
  • vii)
int x = 10;
int *p = &x;

auto p1 = &p;   // p1 ?
auto* p2 = &p;  // p2 ?
auto** p3 = &p; // p3 ?

Cevap

  • i) int
  • ii) long int
  • iii) double
  • iv) list
  • v) Geçersiz! 2011 Standartlarında geçerliyken artık geçersiz. Ancak 1 değer içeren küme parantezinde tipi int olurken birden fazla eleman alacağı zaman auto x = {,,,} şeklinde atama yapılması gerekir.
  • vi) x1 için int *x1 = &x; ve x2 için int *x2=&x;
  • vii) p1, p2, p3 eşitliğin sağ taraflarında işaretçinin adresi (&p) olduğu için pointer to pointer (int **px) olmak zorunda. auto'ların değerleri buna göre:
int x = 10;
int *p = &x;

auto p1 = &p;   // auto ==> int**  Çünkü p1'in türleri int** olacaktır
auto* p2 = &p;  // auto ==> int*   Çünkü p2'nin türleri int** olacaktır 
auto** p3 = &p; // auto ==> int    Çünkü p3'ün türleri int** olacaktır

Soru [references auto c++ intermediate medium]

auto ile belirtilen ifadelerin doğru veya hatalı olduğunu belirtiniz.

  • i) auto x;
  • ii) auto x=5, y;
  • iii) auto x=5, y=2.5;
  • iv) auto x(10), y{x};
  • v) const auto x {10}, y=5;
  • vi) static auto x=10;

Cevap

  • i) Hatalı! Sağ taraf tanımı olmak zorundadır.
  • ii) Hatalı! x için değer int olacak ve y için de bu tip kullanılacak ancak atama olmaksızın bir auto tanımı kullanamayız.
  • iii) Hatalı! Çünkü auto x=5 ifadesiyle auto için int tespit edilmiş ancak y=2.5 ile double olması gerekir anca tek satırda tanımlı oldukları için sözdizimi hatası alırız.
  • iv) Geçerli. x Değişkeni int türünde ve 10 değerine sahip olmuş ve ardından y=x ataması yapılmış.
  • v) x ve y sabit ve başlangıç değerlerine sahip int türünde başlatılır.
  • vi) static int olarak x tanımlanmış olur.

Soru [static auto c++ easy begginer]

Çıktı ne olur?

int main() {
  for(int i=0;i<10;i++) {
    static auto x = 5;
    std::cout << x++ << " ";
  }
}

Cevap

5 6 7 8 9 10 11 12 13 14


Soru [references c++ intermediate medium]

auto Hangi türe denk gelecektir?

auto&& p = 20;

Cevap

&& iki tane referans deklaratörü kullanılırsa forwarding referans deklaratörü denir. 20 değeri int türündedir ve int &&p olacaktır.


Soru [references c++ intermediate medium]

Aşağıdaki auto ile çıkarılan fonksiyon işaretçisinin typedef ile tür çıkarımını yaparak çağırınız.

int foo(int);
int main() {
  auto f1 = &foo;
}

Cevap

typedef int(*foo_işaret_eden_tür_adı)(int); ile foo işlevinin türünü çıkarır ve f1 değişkenini bu türden yaratarak foo işlevini değer olarak atarız.

int foo(int);
int main() {
  typedef int(*foo_def)(int);

  foo_def f1 = foo;

  f1(12); 
}

Soru [references c++ intermediate medium]

void func(int* p);
void func(int& r);
  • i) Yukarıdaki iki fonksiyonun aynı sınıfta tanımlanması halinde function overloading sağlanır mı?
  • ii) Overloading oluyor ise bu senaryo tercih edilir mi, neden?

Cevap

  • i) Evet ikisinin aynı sınıfta olması function overloading demektir
  • ii) Tercih edilmez çünkü ikisi de aynı şekilde "call by reference" fonksiyonu olup kodlama düzeyinde ayrıştıralamaz benzerliktedirler.

Soru [c++ internediate medium decay-to-pointers array-to-pointer]

int a[3]{};
  auto x1 = a;
  auto x2 = &a;

Yukarıdaki koda göre x1 ve x2 değişkenlerinin türleri ne olacaktır?

Cevap

auto anahtarıyla tanımlanan değişkene bir dizi atandığında da array to pointer decay dönüşümünü görürüz. a Bir dizidir ve x1 değişkenine atandığında dizinin işaretçiye dönüştürüldüğünü görürüz.

Ancak a'nın adresini atadığımızda &a, 3 boyutlu bir diziyi işaret ettiği için bu kez x2 değişkenine 3 boyutlu bir diziyi gösteren pointer olarak ataması yapılır.


Soru [c++ internediate medium decay-to-pointers function-to-pointer]

int foo(int);

int main() {
  auto f1 = foo;
  auto f2 = &foo;
  auto &f3 = foo;
  auto f4 = &f1;
}

f1, f2, f3 ve f4'ü tanımlayan auto ifadelerinin türleri nedir?

Cevap

foo Fonksiyonunu f1, f2 ve f3 değişkenlerine atarken auto anahtarının alacağı değerler;

  • f1 için function-to-pointer dönüşümü ile int (*f1)(int) . Buradaki atama implicit (örtülü) olacak (f1 = foo) yani foo işlevinin derlenmiş bu ikili dosyadaki yerini f1 işaretçisine atama işini derleyici anlayıp int (*f1)(int) olacak şekilde tamamlayacak.
  • f2 için foo işlevinin bellek adresini aldığımızda (&foo) atamasını da bir işaretçiye yapacağız doğal olarak. Burada &foo ile explicit (aşikar) bildirim yapıyoruz. function-to-pointer dönüşümü ile int (*f1)(int)
  • f3 için bir decay dönüşümü (burada function to pointer dönüşümü) olmadan int (&f1)(int)
  • f1'in pointer to function olduğunu (int (*f1)(int)) biliyoruz. f4 ise pointer to pointer to function olacaktır. Yani işaretçinin işaretçisi olur:
int (*f1)(int) = foo;
int (**f4)(int) = &f1;
Kaynak

Soru [c++ internediate medium pass-by-reference pass-by-value]

  • pass by value ile pass by reference arasındaki fark nedir? Ne için hangisini tercih etmeliyiz?
  • Ne zaman pass by pointer kullanırız?

Cevap

  • Eğer belleği daha verimli kullanmak istiyorsak pass by reference kullanabiliriz
  • Eğer çağırdığımız işlevin içinde argümana geçirdiğimiz değişkenin değerinin değişmesini istemiyorsak pass by value kullanmalıyız.
  • Eğer çağırıdğımız işlev işaretçi argüman alıyorsa (void func(int *p1){}) ya işaretçi bir değişkeni (int x=10; int *y=&x; func(y);) ya da adresi (int x=10; func(&x);) parametre olarak geçireceğiz.
Kaynak

Soru [reference-value c++ internediate medium pass-by-reference pass-by-value]

int main(){
  int x = 10;
  // func(x);
  cout << x;
}

func(...) fonksiyonunu görmeden x'in değerinin kaç olacağını söyleyebilir misiniz?

Cevap

x'in pass by reference veya pass by value olarak gönderilip gönderilmediğini func isimli fonksiyonun bildirimini görmeden söyleyemeyiz. Eğer değer olarak geçirilmişse 10 ancak referans olarak geçirilmişse farklı bir değerde olabilir.

#include <iostream>
using namespace std;

// Aşağıdaki tüm func işlevleri geçerlidir

//void func(int c) {
//	cout << c;
//}

//void func(const int c) { 
//	cout << c;
//}

//void func(const int& c) {
//	cout << c;
//}

//void func(const double& c) {
//	cout << c;
//}

void func(const char& c) {
	cout << c;
}

int main() {
	int x = 100;
	func(x);
}
Kaynak

Soru

Aşağıdaki atamalar doğru mudur, yanlışsa neden?

unsigned int uval{ 56u };
int* p = &uval;

int& r = uval;

Cevap

Her iki atama da yanlıştır çünkü ister pointer ister referans semantiği farklı tipte değeri kabul etmez. Tür uyuşmazlığı doğar.


Soru

int a[5][10][20]{0};

Aşağıdaki değerleri atayacağımız sol taraf referans değerini ifadesini yazınız.

  • i) a[1][2][5]
  • ii) a[1][2]
  • ii) a[0]

Cevap

  • i) int& r = à[1][2][5]
  • ii) int(&r)[5] = a[1][2]
  • ii) int(&r)[2][5] = a[0]

Soru

İki int türünde değişkenin değerlerini takas yapacak şekilde hem işaretçi hem referans değişkenler kullanarak fonksiyonları yazınız.

Cevap

void swap_p(int* p1, int* p2){
  int temp = *p1;
  *p1 = *p2;
  *p2 = temp;
}

void swap_ref(int& r1, int& r2){
  int temp = r1;
  r1 = r2;
  r2 = temp;
}

int main(){
  int a = 5;
  int b = 10;
  swap_p(&a, &b);
  swap_ref(a, b);
}

Soru

"Function returning pointer" diye adlandırılan, int türünde bir değeri hem işaretçi hem referans değer olarak dönen fonksiyonu yazınız.

Cevap

int i = 10;

int* func_p(){
  return &i;
}

int& func_ref(){
  return i;
}

int main(){
  int* p = func_p(); // NOT: L value referansa atanırken -> int& ref = *func_p()
  *p = 20;
  
  func_ref() = 20; // i'nin değerine 20 atanmış olur.
}

Soru

int* func_p(); ile bildirimi yapılan fonksiyonun genel adı nedir?

Cevap

Function returning pointer


Soru

T func() bildiriminde T nin hangi türler için func() fonksiyonu R, hangi türler için L Value ifadesidir.

Cevap

func Fonksiyonunun dönüş değerinin türü (yani T);

  • referans türünde ise L value expression,
  • değer türünde ise (double, int, date, struct vs.) PR value expression.

Soru

Statik ömürlü nesne ne demektir? Neler statik ömürlüdür?

Cevap

Programın sonuna kadar hayatta kalacak nesnelere statik ömürlü nesneler denir.

  • Global değişkenler
  • static local variables
int& foo(){
  static int x = 11;
  return x;
}

Soru

Otomatik ömürlü nesneler tanımlandığı kapsamın bitmesi halinde hayatları sonlanır. int& foo(void); bildirimli fonksiyonun döndüreceği değer otomatik ömürlü olması halinde dangling referans veya dangling pointer olacaktır ve tanımsız değerlere neden olacaktır. Buna göre nasıl değişkenler tanımlanabilir?

Cevap

  • Statik ömürlü nesne (programın sonuna kadar hayatta kalacak nesne)
    • global değişken
    • static local variable
  • Dinamik ömürlü bir nesne olmalıdır (bu durumda dinamik ömürlü nesnenin işi bitince bellek bloğunun geri verilmesi sorumluluğu, foo fonksiyonunu çağıran fonksiyondadır)

Soru

int x = 2; ifadesindeki x değişkenini sadece okumak amaçlı olacak (set veya mutate etmeyecek) işaretçiyi nasıl tanımlarsınız (pointer to const int)?

Cevap

const int* p = &x; Burada p işaretçisi "x'in değerini değiştirmek üzere dereference edilmeyeceğim" diyor. Yani p işaretçisi yeni bir değer ataması için dereference edildiğinde *p = 22 daima hata verecek:

int x = 10;
const int* p = &x;
*p = 22; // error: assignment of read-only location '* p'

Soru

int y = 1; ifadesindeki y değişkenininin değerini değiştirebilen (set/mutate edebilen) ancak başka bir değişkeni işaret edemeyecek bir işaretçiyi nasıl tanımlarsınız (const pointer to int)?

Cevap

int* const p = &y; Burada p işaretçisi "hayatım boyunca y 'yi göstereceğim" diyor. Aşağıdaki kod hata verecektir.

int z = 1;
int x = 10;
int* const p = &z;
p = &x; // "error: assignment of read-only variable 'p'"

Soru

pointer to const int const int* p = &y; ifadesindeki p işaretçisi y değişkeninin değerine sadece erişebilir (accessor/getter) yani y değişkenine p işaretçisi dereference edilerek yeniden değer atanamaz (Örn. *p = 12).

int y = 10;
const int* p = &y;
*p = 12;
/*
error: assignment of read-only location '* p'
   *p = 12;
        ^~
*/

Buna göre; işaretçi yerine sol taraf referans değişkeni kullanarak, getter/accessor olacak şekilde bir değişken bildirimi yapan ifadeyi yazınız?

Cevap

const int& r = y ile bildirim yapılabilir.

int y = 10;
const int* p = &y;
*p = 12; 
/*
error: assignment of read-only location '* p'
   *p = 12;
        ^~
*/

// L Value Reference ifadesi
const int& r = y;
r = 22;
/*
error: assignment of read-only reference 'r'
  r = 22;
      ^~
 */

Soru

const pointer to int olarak isimlendirilen int* const p = &y; ifadesindeki p işaretçisi sadece y değişkenini işaret eder ve farklı bir değişkeni işaret etmesi için tekrar atama yapılamaz.

int x = 1;
int y = 10;
int* const p = &y;
p = &x;
/*
error: assignment of read-only variable 'p'
 p = &x;
      ^
*/

Buna göre; işaretçi yerine sol taraf referans değişkeni kullanarak, ilk değerinden başka bir değere atama yapılmayacak şekilde ifadeyi yazınız?

Cevap

L Value referanslar zaten ilk atandıkları değerden başka bir değere atanamazlar. Bu yüzden fazladan bir tanımlamaya ihtiyaç yoktur. Aşağıdaki r = y atamasıyla sadece x in değerine y nin değeri atanır ancak r yine x e bağlanmaya devam eder.

int main(){
  int x = 1;
  int& r = x;
  cout << "x: " << x << " | &x: "<< &x << " | &r: "<< &r << endl; 
  //       x: 1           | &x: 0x61fe14    | &r: 0x61fe14

  int y = 2;
  r = y;
  cout << "x: " << x << " | &y: " << &y << " | &r: "<< &r << endl; 
  //       x: 2           | &y: 0x61fe10     | &r: 0x61fe14
}

Soru [c++ intermediate medium top-level-const]

  1. const int* p1 = &x
  2. int const *p2 = &x
  3. const* int p3 = &x
  4. int* const p4 = &x

Yukarıdaki ifadelerde aynı işi yapanları bulunuz ve ifadelerin ne anlama geldiklerini yazınız?

Cevap

  • const int* p1 = &x == int const *p2 = &x p1 ve p2 aynıdır ve bu iki işaretçi const ile accessor/getter olarak tanımlanmıştır. p1 ve p2 farklı bir değişkeni işaret edebilir ancak derefrence edilerek x'in değeri bu işaretçiler üstünde değiştirilemez (setter/mutator olarak kullanılamaz). Yazılıma başlanmadan önce hangi biçimde yazılacağı karar verilmesi gereken başlıklardandır aksi halde kodu okurken bir karmaşaya mahal verilebilir.
int main(){
  int x = 10;
  const int* p1 = &x;
  cout << "*p1 : " << *p1 << " - &p1 : " << &p1 << endl; // *p1 : 10 - &p1 : 0x61fe10
  
  int const *p2 = &x;
  cout << "*p2 : " << *p2 << " - &p2 : " << &p2 << endl; // *p2 : 10 - &p2 : 0x61fe08

  // p1 ve p2 dereference edilerek x'in değerini değiştiremez
  *p1 = 33;   // error: assignment of read-only location '* p1'
  *p2 = 44;   // error: assignment of read-only location '* p2'

  // ancak farklı bir in türünden değişkeni işaret edebilirler
  int y = 20;
  p1 = &y;
  p2 = &y;

  cout << "*p1 : " << *p1 << " - &p1 : " << &p1 << endl; // *p1 : 20 - &p1 : 0x61fe10
  cout << "*p2 : " << *p2 << " - &p2 : " << &p2 << endl; // *p2 : 20 - &p2 : 0x61fe08
}
  • const* int p3 = &x tanımı hatalıdır. const* ile error: expected unqualified-id before 'int' hatası alınır.
  • int* const, diğer adıyla top level const. int* const p4 = &x ile p4 işaretçisinin farklı bir değişkene işaretçi olmasının önüne geçiliyor.
int main(){
  int x = 10;
  int* const p4 = &x;

  cout << "*p4 : " << *p4 << " - &p4 : " << &p4 << endl; // *p4 : 10 - &p4 : 0x61fe10

  int y = 20;
  *p4 = y;
  cout << "*p4 : " << *p4 << " - &p4 : " << &p4 << endl; // *p4 : 20 - &p4 : 0x61fe10
  p4 = &y;
  /*
  error: assignment of read-only variable 'p4'
   p4 = &y;
         ^
  */
}

Soru

int z = 1; ifadesindeki z değişkenininin değerini değiştirebilen (set/mutate edebilen), başka bir değişkeni de işaret edebilecek bir işaretçiyi nasıl tanımlarsınız?

Cevap

int z = 1;
int x = 10;
int* p = &z;
cout << *p << endl; // 1
p = &x;
cout << *p << endl; // 10

Soru

void Dönen, integer değer alabilen bir mutator/setter ve işaretsiz tam sayı değer alabilen bir accessor/getter olmak üzere iki parametreli fonksiyon bildirimi yazınız.

Cevap

void foo(int* mutator, const unsigned int* accessor);


Soru

const int* foo();

int main(){
  cout << ++*foo() << endl; // ?
}

Ekrana ne yazar?

Cevap

const int* foo() veya referans ifadesiyle const int& foo() fonksiyonunun dönen değeri değiştirilemez yani immutable döneceği için ++ operatörü hata verecektir.

int i = 10;
const int* foo() {
  return &i;
}

int main(){
  cout << ++*foo();
/*
error: increment of read-only location '* foo()'
   cout << ++*foo();
                  ^
*/
}

Soru [c++ beginner easy]

Aşağıdaki kod geçerli midir, geçerli ise çıktıları yazınız.

int x = 10;
double d = 1.66;
d = x;
cout << d << endl; // ?
d = x * 1.666;
cout << d << endl; // ?
x = d;
cout << x << endl; // ?

Cevap

int x = 10;
double d = 1.66;
d = x;
cout << d << endl; // 10
d = x * 1.666;
cout << d << endl; // 16.66
x = d;
cout << x << endl; // 16

Soru [c++ beginner easy]

Aşağıdaki kodun çıktısı nedir?

const int& func();
int main(){
  func() = 10;
  cout << func();
}

Geçerli midir, değilse neden?

Cevap

fonksiyon const dönüşlü ve 10 değerini atamaya çalıştığımız için hata alırız.

const int& func();

int main(){
  func() = 10;
  cout << func();
/*
  error: assignment of read-only location 'func()'
   func() = 10;
            ^~
*/
}

Soru [c++ beginner easy]

Kod geçerli midir? Çıktısı varsa nedir?

void fonk_p(const int* x){
  cout << x;
}
void fonk_r1(const int& x){
  cout << x;
}
void fonk_r2(int& x){
  cout << x;
}

int main(){
  double d = 10.16;
  fonk_r1(d);
  fonk_r2(d);
  fonk_p(&d);
}

Cevap

  • double değeri int değere referans veya pointer bir değişkene atarken tür uyuşmazlığı hatası alırız bu yüzden fonk_r2 fonksiyonu double -> int& dönüşümü hata verecektir. Eğer bu dönüşüm double -> const int& şeklinde olsaydı hata alınmaz ancak veri kaybı yaşanabilir.
  • Referans olarak çalışan fonk_r1 fonksiyonu hatasız çalışır ancak double değer int dönüşümünde veri kaybı yaşanır ve çıktı 10 olur.
  • Ancak işaretçi parametre alan fonk_p hata üretir:
error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
   fonk_r2(d);
           ^
note:   initializing argument 1 of 'void fonk_r2(int&)'
 void fonk_r2(int& x){
      ^~~~~~~
error: cannot convert 'double*' to 'const int*'
   fonk_p(&d);
          ^~
note:   initializing argument 1 of 'void fonk_p(const int*)'
 void fonk_p(const int* x){
             ~~~~~~~~~~~^

Soru [c++ beginner easy]

Aşağıdakilerden hangisi const int x = 3; fun( x ); kodunun çalışmasını sağlar:

A) void fun (int x); B) void fun (int& x); C) void fun (const int& x); D) A and C

Cevap

  • Eğer değer olarak geçirelecekse fun fonksiyonunun int türünden parametre alması yeterlidir (A).
  • Eğer referans olarak geçirilecekse ya fun(&x) veya fun(x) şeklinde geçirilebilir ve bu durumda ya void fun(int* x) ya da void fun(int& x) olmalı. x bildirilirken const int verildiği için B yanlış, C de doğrudur.
  • Cevap D.

Soru [c++ begginer easy]

Hangisi doğrudur?

  • A) const int& x;
  • B) const int x = 3; int *p_int = & x;
  • C) const int x = 12; const int *p_int = & x;
  • D) int x = 3; const int y = x; int& z = y;

Cevap

  • A) Yanlış. Referans değerlerin varsayılan başlatıcıları yoktur, bir değişken atamasının bildirimleriyle birlikte yapılması gerekir.
  • B) const int x değişkeni const int* türünde bir işaretçiye atanmalıdır.
  • C) Doğru
  • D) Yanlış. const int y değişkeni const int& z referansına atanmalıdır.

Soru [c++ internediate medium]

int x = 10;
const double& rd = x;

Geçerli midir, değilse neden?

Cevap

Geçerlidir. double& rd = 10; ataması geçersizdir çünkü bir referansı doğrudan değer ile başlatamaz muhakkak bir nesne ile başlatmamız gerekir. Ancak const double& rd = 10 ifadesindeki const sayesinde makina kodunda önce geçici bir double değişkeni oluşturulur ve o değişkene 10 değeri atandıktan sonra bu geçici double değişkeni rd referansına bağlanır.

void ref(){
    double d = 10;  // movsd   xmm0, QWORD PTR .LC0[rip]
                    // movsd   QWORD PTR [rbp-16], xmm0
    double& r (d);  // lea     rax, [rbp-16]
                    // mov     QWORD PTR [rbp-8], rax
}

void const_ref() {
    const double& dref = 10;  // movsd   xmm0, QWORD PTR .LC0[rip]
                              // movsd   QWORD PTR [rbp-16], xmm0
                              // lea     rax, [rbp-16]
                              // mov     QWORD PTR [rbp-8], rax
}

Soru [c++ beginner easy]

Aşağıdaki kod geçerli midir, geçerli ise çıktıları yazınız.

int x = 10;
double* pd = x;
d = x;
cout << d << endl; // ?
d = x * 1.666;
cout << d << endl; // ?
x = d;
cout << x << endl; // ?

Cevap

int x = 10;
double d = 1.66;
d = x;
cout << d << endl; // 10
d = x * 1.666;
cout << d << endl; // 16.66
x = d;
cout << x << endl; // 16

Soru [c++ internediate medium]

Aşağıdaki kod için şunlar söylenebilir mi?

  • fonk_1 fonksiyonuna sadece L Value parametre olarak geçirilebilir
  • fonk_2 fonksiyonuna L ve R Value değerler parametre olarak geçirilebilir
void fonk_1(T&)
void fonk_2(const T&)

Cevap

Doğru


Soru [c++ internediate medium]

Aşağıdaki ifadenin function pointer ifadesini yazınız.

double bol(int a, int b){return a/b;}

int main(){
  ????fn???? = bol;
  cout << fn(11,2); // 5
}

Cevap

double bol(int a, int b){return a/b;}

int main(){
  double (*fn)(int, int) = bol;
  cout << fn(11,2); // 5
}

Soru [c++ internediate medium]

Aşağıdaki ifadelerden hangileri doğrudur?

  • A) Referans değerler varsayılan değerle başlatılabilir ancak işaretçiler bir değere atanmadan tanımlanamazlar. int* p; tanımı yapılabilirken int& r; tanımlanamaz.
  • B) Pointer değişkenin kendi adresini alabiliriz ama referans değişkenin adresi bağlandığı değişkenin adresini verir.
  • C) Function pointer (fonksiyona işaretçi) gibi function referans (fonksiyona referans) da vardır.
  • D) Elemanları pointer ve referans olan dizi tanımlanabilir.
  • E) Bir referans tıpkı işaretçiler gibi farklı değişkenlere atanabilir.

Cevap

  • A) Tam tersi doğrudur. Referans değerler varsayılan olarak başlatılamaz ancak işaretçiler değer ataması olmadan tanımlanabilirler.
  • B) Doğru
  • C) Doğru
double bol(int a, int b);

double (*fn1)(int, int) = bol;
// veya
double (*fn2)(int, int) = &bol;
// aynı şekilde fonksiyona referans olarak da tanımlanabilir
double (&fn2)(int, int) = bol;
  • D) Yanlış. Elemanları pointer olan dizi olabilir ancak elemanları referans olan dizi yoktur. Reference wrapper sınıfı ile tekrar bağlanabilir (rebindable) referans oluşturabilir ve elemanları referans olan bir dizi tanımlanabilir.
int x, y, z;

int* pointerArray[] = {&z, &x, &y}; // pointer dizi geçerlidir
int& pointerArray[] = {z, x, y}; // referans dizi tanımlanamaz
/*
error: declaration of 'pointerArray' as array of references
 int& pointerArray[] = {z, x, y};
*/
  • E) Yanlış. Bir işaretçi değişken eğer const T* p olarak tanımlanmamışsa başka bir değişkene gösterecek şekilde atanabilir. Ancak referans değişkenler sadece bir değişkeni işaret eder ve başka bir değişkene bağlanamaz.
Kaynak

Soru [auto c++ internediate medium]

Aşağıdaki auto anahtarının kullanımlarından hangileri doğrudur?

  • i)
void func(auto x){ 
  //
}
  • ii)
auto func()->int { 
  return 1; 
}
  • iii)
auto func() {
  return 1; 
}
  • iv)
template <typename FirstType, typename SecondType> 
auto add(FirstType a, SecondType b) -> decltype(a + b){
   return a + b;
}
  • A) i
  • B) i ve ii
  • C) ii, iii, iv
  • D) hepsi

Cevap

Doğru cevap D (hepsi) olacak.

Sondaki dönüş türü (trailing retur type) özelliği, dönüş türünün fonksiyonun argümanlarının türlerine bağlı olması halinde, fonksiyon şablonunun dönüş türünün genelleştirilemeyeceği bir C++ sınırlamasını kaldırır. Örneğin, a ve b, çarpım fonksiyonun parametreleri olsun (const A &a, const B &b). Burada a ve b rastgele türlerdir. Sondaki dönüş türü özelliği olmadan, a*b için tüm durumları genelleştirmek için çarpma işlevi şablonu için bir dönüş türü bildiremezsiniz. Bu özellik ile fonksiyon argümanlarından sonra dönüş tipini belirtebilirsiniz.

  • iii = auto return type diye isimlendirilir.
  • iv)
#include <iostream>
template <typename FirstType, typename SecondType> 
auto add(FirstType a, SecondType b) -> decltype(a + b){
   return a + b;
}

using namespace std;

int main(){
   // The first template argument is of the integer type, and
   // the second template argument is of the character type.
   cout << add(1, 'A'); 

   // Both the template arguments are of the integer type.
   cout << add(3, 5); 
}

Soru [auto easy]

Tür çıkarımlarında kullanılan anahtar sözcükler nelerdir?

  • i) auto
  • ii) pointer
  • iii) decltype
  • iv) decltype(auto)
  • v) template

A) i, ii, iii B) i, ii, iv C) hepsi D) i, iii, iv, v

Cevap

Doğru cevap D şıkkı. auto, decltype, decltype(auto), template


Soru [pointer scope c++ internediate medium]

Aşağıdaki işaretçilerin (pglobal, plocal, pstatic, p) değerlerini yazınız.

#include <iostream>

int* pglobal;

int main(){
  int* plocal;
  static int* pstatic;
  int* pinited{};
  int* pnull = nullptr;
}

Cevap

Başlatılmamış global ve static işaretçiler nullptr değeriyle tanımlanmış olur.

Varsayılan değeriyle başlatılmış işaretçi değişkenlerin değeri türün varsayılan değeriyle başlar.

  • pglobal > nullptr
  • plocal > garbage value (otomatik ömürlü işaretçiler çöp değer ile başlatılır)
  • pstatic > nullptr (static anahtarıyla başlatılanlar nullptr ile başlatılır)
  • pinited > 0 (varsayılan değer ile başlatılanlar türün varsayılan değerini alır. int için 0)
  • pnull > nullptr
int* pglobal;

int main(){
  int* plocal;
  static int* pstatic;
  int* p{};
  int* pnull = nullptr;
  cout << pglobal << endl;  // 0
  cout << plocal << endl;   // 0x737fb0
  cout << pstatic << endl;  // 0
  cout << p << endl;        // 0
  cout << pnull << endl;    // 0
}
bool* pnull = nullptr;
bool* pinited{};
bool* pglobal;

int main(){
  bool* plocal;
  static bool* pstatic;
  cout << "pnull  : " << pnull << endl;    // 0
  cout << "pinited: " << pinited << endl;  // 0
  cout << "pglobal: " << pglobal << endl;  // 0
  cout << "plocal : " << plocal << endl;   // 0x10
  cout << "pstatic: " << pstatic << endl;  // 0
}

Soru [reference-value beginner easy]

Sağ ve sol taraf referanslarını nasıl ifade ediyoruz?

Cevap

Örneğin int türünden referanslar oluşturmak isteyelim: int& lv sol taraf referansını, int&& rv ise sağ taraf referansını verir.

int x = 10; ifadesinde x, sol taraf değeri ve 10 ise sağ taraf değeridir. Sol taraf referansına sol taraf değeri atanırken (int x=10; int& lv=x;), sağ taraf referansına sağ taraf değeri atanır (int&& rv=10;). Doğrudan değeri atayabileceğimiz sağ taraf referansıyken bir değişkeni atadığımız ise sol taraf referansıdır.

Eğer sağ taraf referansına sol taraf referansı atarsak:

int x = 10;
auto&& r1 = 10; // buraya kadar sağ taraf referansına 10 değeri atıyoruz
// ancak aşağıda ise sağ taraf referansına (&&r), sol taraf referansı atıyoruz 
// bu durumda reference collapsing meydana geliyor
auto&& r2 = x;

Bu koda göre ifadelerin auto olmaksızın tanımı:

int x = 10;
auto&& r1 = 10; // int &&r1 = 10
auto&& r2 = x;  // int  &r2 = x

Soru [reference-value intermediate medium typedef]

using mytype = int &&;

int main(){
  int x = 5;

  mytype&& x1 = 10;
  mytype& x2 = 10;
  mytype& x3 = x;
}

x Değişkenlerine atamalar geçerli midir, türleri ne olur?

Cevap

using mytype = int &&; ile bir tip tanımı yapılıyor. int türünde sağ taraf referansına (int &&) mytype ismi veriliyor. mytype tipinden bir değişken yaratırken türü int && olacaktır.

mytype&& x1 = 10; // mytype Türünde x1 değişkeni sağ taraf referansıdır ve 10 değeri atanır (Geçerli) 
mytype& x2 = 10; // int &x2 türünde sol taraf referansıdır ve sağ taraf değeri atanamaz (Hatalı) 
mytype& x3 = x;  // int &x2 türünde sol taraf referansıdır ve sol taraf değeri olan x atanabilir (Geçerli)

Soru [reference-value beginner easy]

const int&& x = 10;

Sağ taraf referansları const ile tanımlanabilir mi?

Cevap

Evet tanımlanabilir ama pratikte anlamlı değildir.


Soru [reference-value beginner easy]

Aşağıdaki fonksiyonların hangilerine L Value/R Value geçirebiliriz?

void f1(T&)
void f2(T&&)
void f3(cont T&)
L Value R Value
f1 ? ?
f2 ? ?
f3 ? ?

Cevap

L Value R Value
f1 Evet Hayır
f2 Hayır Evet
f3 Evet Evet

Soru [reference-semantic beginner easy]

Neden sol taraf referans semantiğini kullanırız?

Cevap

Pointer semantiği ile aynı çıktıyı verir ve kodlamamızı ve kodun okunabilirliğini daha kolay kılar. Değere ulaşmak için sürekli dereferencing (*ptr) yapmamız gerekmez.


Soru [size beginner easy]

using std::cout;
using std::endl;
using std::size;

int main(){
  float puanlar[]{10, 22.5, 77.4, 21.5};
  for(int i=0; i<size(puanlar)){
    cout << "puan: " << puanlar[i] << endl;
  }
}

c++ 17 ile birlikte gelen size() fonksiyonu yerine neden C# veya javadaki gibi dizinin length türünde bir özellik yoktur.

Cevap

C++'da diziler bir nesne değildir.


Soru [brace-initializer array beginner easy]

  float not1[]{10, 22.5, 77.4, 21.5};
  float not2[19]{10, 22.5, 77.4, 21.5};
  float not3[2]{10, 22.5, 77.4, 21.5};

Yukarıdaki değişkenler için derleyicinin çıktısı ne olur?

Cevap

  float not1[]{10, 22.5, 77.4, 21.5};   // sorun yok. brace intializer ile verilen eleman sayısı kadar dizinin elemanı olur. 4 Elemanlı dizi oluşturur.
  float not2[19]{10, 22.5, 77.4, 21.5}; // sorun yok. tanımsız olan elemanlar (ilk 4 eleman hariç kalanlar) 0 değeriyle başlatılır.
  float not3[2]{10, 22.5, 77.4, 21.5};  // hata verir. dizinin eleman sayısından fazla eleman brace initializer içinde tanımlı olamaz.

06 - 04/09/2022

Soru [beginner easy auto]

auto için yapılan tür çıkarımları nelerdir?

auto x{1};    // auto ??
auto y = {1}; // auto ??
auto z{1,2,3};// auto ??
auto k(1);    // auto ??

auto p1 = &x;   // auto ??
auto* p2 = &x;  // auto ??

Cevap

auto x{1};    // auto > int
auto y = {1}; // auto > std::initializer_list<int>
auto z{1,2,3};// auto > hatalı (C++ 11 için std::initalizer_list<int> idi ama artık geçersiz )
auto k(1);    // auto > int
auto p1 = &x;   // auto > int* p1
auto* p2 = &x;  // auto > int* p2

Soru [intermediate medium pointer auto]

p1, p2, p3 için yapılan tür çıkarımları nelerdir? Her satırda auto için yapılan tür çıkarımları nelerdir?

int x{1};
int* ptr = &x;

auto   p1 = &ptr; // p1 ?? , auto ??
auto*  p2 = &ptr; // p2 ?? , auto ??
auto** p3 = &ptr; // p3 ?? , auto ??

Cevap

&ptr'nin türü int** olduğuna göre p1, p2 ve p3'ün türleri int** olacaktır

auto ise ilk satırda int**, ikinci satırda int* ve üçüncü satırda int olacaktır.


Soru [intermediate medium reference-collapsing reference]

Referece collapsing nedir?

Cevap

C++ reference to reference desteklemez ve bu durum oluştuğunda dilin reference collapsing kuralları devreye girer.

/*
Sağ taraf referansı atandığı için yani doğrudan değeri atadığımızda: 
auto > int tür çıkarımı olacak
Bu durumda "auto &&r1 > int &&r" yani SAĞ TARAF REFERANSI olacak.
*/
	auto &&r1 = 5; // auto &&r > int &&r

/*
Sol taraf referansı atandığı için yani doğrudan değer yerine 
nesneyi bağladığımızda: "auto > int &" tür çıkarımı olacak 
int &r ile SOL TARAF REFERANSI tanımlanmış olacak.
*/
	int x{1};
	auto &&r2 = x; // auto &&r > int &r

// Özetle auto sayesinde SOL veya SAĞ TARAF REFERANSI dinamik olarak tanımlanıyor.
// mytype : SAĞ TARAF REFERANSI 
using mytype = int&&;

int main() {
	mytype r1 = 10; // sağ taraf referansına 10 değerini atıyoruz
	mytype&& r2 = 20; // mytype RValue idi ve mytype&& da RValue
	/*
  referans deklaratörünü sol taraf referansına çevirsek: mytype&
  reference collapsing meydana gelir çünkü sol taraf referansını sağ taraf referansına bağlayamayız.
  */
  mytype& r3 = 30; // REFERENCE COLLAPSING
}

Soru [beginner easy sizeof]

sizeof kullanımlarından hangileri doğrudur ve çıktıları nedir?

auto x{1};
auto &&r = x;
cout << r << endl;
cout << sizeof(x) << endl;
cout << sizeof r << endl;
cout << sizeof(int) << endl;

Cevap

sizeof eğer bir tür için boyut dönecekse parantez içinde operand olarak verilmelidir. Bunun dışındaki kullanımlarında yani bir değişken için çalışacaksa parantez içinde operand olarak alması gerekmez.

auto x{1};
auto &&r = x;
cout << r << endl;          // 1
cout << sizeof(x) << endl;  // 4
cout << sizeof r << endl;   // 4
cout << sizeof(int) << endl;// 4

Soru [beginner easy]

Declaration Type anlamıa gelen declytpe kullanımlarından hangileri doğrudur?

i.

Cevap


Soru [beginner easy practice integra-promotion ascii]

Kullanıcıdan küçük harfle bir karakter girmesini isteyen ve büyük harf olarak ekrana yazan bir uygulama yazınız.

Cevap

#include <iostream> 
using namespace std; 

int main() { 
  char lowerCaseLetter, upperCaseLetter; 
  int offset; 
  cout << "Please enter a lower case letter:" << endl; 
  cin >> lowerCaseLetter; 
  offset = (int)(lowerCaseLetter - 'a');
  upperCaseLetter = (char)('A' + offset); 
  
  cout << "The upper case of " << lowerCaseLetter << " is " << upperCaseLetter << endl; 
  return 0; 
} 

image

repl.it Kodu


Soru [beginner easy practice cmath]

Kullanıcıdan yarı çapını istediğiniz dairenin alanını hesaplayan ve ekrana yazan uygulamayı kodlayınız.

Cevap

#include <iostream> 
#include <cmath> 

using namespace std; 

int main() { 
  double radius, area; 
  cout << "Please enter the radius:" << endl; 
  cin >> radius; 
  area = M_PI * (radius*radius); 
  cout << "The area of a circle with radius of " << radius << " is " << area << endl; 

  return 0; 
}

image

repl.it Kodu


Soru [beginner easy]

Kullanıcıya kaç gün yıllık izni olduğunu sorun ve bunu x hafta y gün olacak şekilde yazdırın.

Cevap

#include <iostream> 

using namespace std; 

const int DAYS_IN_A_WEEK = 7; 

int main() {
  int vacationDays; 
  int fullWeeks, remainingDays; 

  cout << "Please enter number of days you have for vacation:" << endl; 
  cin >> vacationDays; 
  fullWeeks = vacationDays / DAYS_IN_A_WEEK; 
  remainingDays = vacationDays % DAYS_IN_A_WEEK; 
  cout << vacationDays << " days you have " << fullWeeks << " week " << remainingDays << " days" << endl; 
  
  return 0; 
}

image

repl.it kodu


Soru [beginner easy]

Aşağıdaki const ifadelerinin açıklamalarını yazınız?

image

Cevap


Soru [beginner easy]

Cevap


Soru [beginner easy]

Cevap


Soru [beginner easy]

Cevap


Soru [beginner easy]

Cevap


@cemtopkaya
Copy link
Author

Aşağıdaki ifadelerin hangisi yanlıştır

auto x=10, y=2.0;
auto x=10, y=x;
const auto x=10, y=++x;

  • auto x=10, y=2.0; : x değişkeni int olarak yaratıldı ancak y ile aynı auto tanımlayıcısını kullandıkları ve , ile ayrıldıkları için her ikisi de aynı türde çıkarımsanacağı için ve y değeri int olmayacağı için yanlıştır.
  • const auto x=10, y=++x; : x değişkeni const olarak tanımlandığı için ++ ile arttırılamaz
  • auto x=10, y=x; doğrudur.

@cemtopkaya
Copy link
Author

p1, p2, p3 için yapılan tür çıkarımları nelerdir? Her satırda auto için yapılan tür çıkarımları nelerdir?

int x{1};
int* ptr = &x;

auto   p1 = &ptr; // p1 ?? , auto ??
auto*  p2 = &ptr; // p2 ?? , auto ??
auto** p3 = &ptr; // p3 ?? , auto ??

C++ dilinde bu örnekte yapılan şey, auto anahtar kelimesini kullanarak değişken türlerinin C++ tarafından otomatik olarak belirlenmesini sağlamak. Kodu hiç bilmeyen birine anlatmak için önce temel kavramları açıklayalım.

Temel Bilgiler

  1. Değişkenler ve Değerler:

    • int x{1}; ifadesinde, x adlı bir değişken tanımlanır ve içine 1 değeri atanır. Bu değişken, tıpkı bir kutu gibi 1 sayısını saklar.
  2. Adres ve Pointer (İşaretçi):

    • int* ptr = &x; ifadesinde, ptr adlı bir işaretçi tanımlanır. Bu işaretçi, x değişkeninin adresini saklar.
    • Bir işaretçiyi, başka bir kutunun içinde saklı olan bir adres gibi düşünebiliriz. ptr kutusunda x'in adresi var, yani ptr, x’i nerede bulacağını bilir.

auto Anahtar Kelimesi

auto anahtar kelimesi, C++ diline "Bunun türünü ben belirlemeyeyim, sen otomatik olarak çözümle" demek gibidir. Yani, biz auto dediğimizde, C++ bu değişkenin türünü kendisi belirler.

Kod İncelemesi

Kodda üç farklı auto tür tanımı var ve her biri biraz farklı.

1. auto p1 = &ptr;

  • Neye bakıyoruz?: auto burada &ptr ile aynı türü alacak.
  • &ptr nedir?: ptr zaten int* türündeydi, yani ptr bir işaretçi. &ptr ise bu işaretçinin adresini verir. Bu durumda, &ptr aslında bir int** (bir "işaretçiye işaretçi") türüdür.
  • C++ ne yapar?: auto burada int** türünü alır.
  • Sonuç: p1 tür olarak int** olur, yani auto'nun türü int**'dir. p1 artık ptr işaretçisinin adresini saklayabilir.

2. auto* p2 = &ptr;

  • Neye bakıyoruz?: Burada auto* yazılmış, yani auto'nun çözümlediği türe zaten bir * eklenmiş oluyor.
  • &ptr nedir?: Az önce öğrendiğimiz gibi, &ptr bir int** türündedir.
  • C++ ne yapar?: auto, &ptr'nin türü olan int**’yi çözümleyerek alır. Sonra auto* şeklinde yazıldığı için int** olan tür, int*** olarak bir kat daha "işaretçiye işaretçi" olur.
  • Sonuç: p2 tür olarak int*** olur, yani auto'nun çözümlediği tür int** olur, fakat auto* yazıldığından bir * daha eklenir.

3. auto** p3 = &ptr;

  • Neye bakıyoruz?: Burada auto** var, yani auto'nun çözümlediği türe zaten iki * eklenmiş oluyor.
  • &ptr nedir?: &ptr, yine int** türündedir.
  • C++ ne yapar?: auto burada int** türünü alır. Ancak auto** olduğu için bir * daha eklenir ve auto int* olarak çözülse bile iki tane * var, bu durumda p3’ün türü int**** olur.
  • Sonuç: p3 tür olarak int**** olur.

Özet

  • p1 için: int** türündedir.
  • p2 için: int*** türündedir.
  • p3 için: int**** türündedir.

Her bir satırda auto farklı türlerle çalışır ve biz * işaretini ekledikçe işaretçi derecesi artar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment