23 Eylül 2019 Pazartesi

std::default_delete Yapısı

constructor
Örnek
Şöyle yaparız.
std::unique_ptr<int> u5 (new int, std::default_delete<int>());
Örnek
Şöyle yaparız.
std::default_delete<int> d;
std::unique_ptr<int> u4 (new int, d);

gcc Warning Seçenekleri

-w seçeneği
Açıklaması şöyle.
Inhibit all warning messages.
-Wall
Sanılanın aksine tüm warning'leri etkinleştirmez! Açıklaması şöyle.
Note that some warning flags are not implied by -Wall. Some of them warn about constructions that users generally do not consider questionable, but which occasionally you might wish to check for; others warn about constructions that are necessary or hard to avoid in some cases, and there is no simple way to modify the code to suppress the warning. Some of them are enabled by -Wextra but many of them must be enabled individually.
Şöyle yaparız. Aşağıdaki örnekte -msse3 ile sanırım SSE instruction set etkinleştiriliyor.
$ g++ -Wall -msse3 -O3 test.cpp && ./a.out
-Warray-bounds
-Wall ile -Warray-bounds seçeneği de etkinleşir.
Örnek
Şöyle yaparız. Bu hatanın üretilmesine sebep olur.
int arr[10];
return arr[10];
Örnek
Elimizde şöyle bir kod olsunb[9] hatalı kod.
#include <stdio.h>

int main(void)
{
  char b[] = {'N', 'i', 'c', 'e', ' ', 'y', 'o', 'u', '!'};
  printf("b[9] = %d\n", b[9]);

  return 0;
}
Şöyle yaparız
% gcc -O2 -W -Wall -pedantic -c foo.c
foo.c: In function main’:
foo.c:6:5: warning: b[9]’ is used uninitialized in this function [-Wuninitialized]
     printf("b[9] = %d\n", b[9]);
-Wextra
-Wall ile etkinleşmeyen diğer uyarıları etkinleştirir. Şöyle yaparız.

-Werror
Warning'lere error muamelesi yapar. Böylece en ufak warning bile kodun derlenmemesine sebep olur.
Örnek
Şöyle yaparız.
$ g++ -Werror -Wall
Örnek
Extra warning'leri de kullanmak istersek şöyle yaparız.
g++ -Wall -Wextra -Werror ...
-Weffc++
Effective C++ uyarınıların etkinleştirir. Şöyle yaparız.
g++ -std=c++14 -Weffc++ main.cpp
-Wpadded
Açıklaması şöyle.
gcc has the -Wpadded warning that warns when padding is added to a structure:
Örnek
Elimizde şöyle bir kod olsun.
struct X
{
    int a;
    int c;
    double b;
};
Çıktı olarak şunu alırız.
<source>:4:12: warning: padding struct to align 'X::b' [-Wpadded]
    4 |     double b;
      |            ^

<source>:1:8: warning: padding struct size to alignment boundary [-Wpadded]
    1 | struct X
      |        ^


STL Veri Yapısı - Vector Of Bool

Giriş
vector<bool> isminde vector geçmesine rağmen özel bir veri yapısı. 1998 yılında yayınlanan bir yazıda bu sınıfın tam bir container olmadığı belirtiliyor.

Vector of Bool Belleği Farklı Yönetir
Vector Of Bool belleği farklı yönetir. Contiguous bellek sunmak zorunda değildir.
A vector is a sequence container that supports random access iterators. In addition, it supports (amortized) constant time insert and erase operations at the end; insert and erase in the middle take linear time. Storage management is handled automatically, though hints can be given to improve efficiency. The elements of a vector are stored contiguously, meaning that if v is a vector where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + nfor all 0 <= n < v.size().
std:vector<bool>::data Metodu Sağlamaz
Açıklaması burada.

std:vector<bool>::reference tipi prvalue döner
std::vector<bool>::reference proxy bir sınıftır. Bu sınıfı bitleri dışarıya açmak için kullanılır. [] operatörü veya iterator bu proxy sınıfı dönerler.

Proxy sınıfı bir değişkene bağlamak doğru değildir. Bu problem en çok auto şeklindeki kullanımlarda ortaya çıkıyor.

1. prvalue değişkenin lvalue değişkene bağlanması
Aşağıdaki kod derlenmez.
std::vector<bool> boolVector(10);
for(auto& i : boolVector)
    std::cout << i;
Buradaki sorun std::vector<bool>::reference tipinin prvalue (temporary) olması. prvalue bir değişkeni lvalue bir dğişkene bağlayamayız. Şöyle yaparsak sorun çıkmıyor.
for (auto i: boolVector)
  std::cout << i;
2. prvalue değişkenin adresinin alınması
Elimizde şöyle bir kod olsun
std::vector<bool> isInfluenced;
Şu kod anlamsız bir değer döner.
for (int i = 0; i < a->isInfluenced.size(); i++)
  std::cout << &(a->isInfluenced[i]) << " ";
Açıklaması şöyle.
The elements of a vector<bool> cannot be directly accessed like this, because they are/may be smaller than a byte, which is the "resolution" of addresses in C++. So many bits/elements are packed into a single memory location on your computer. But that's not why you get these results.

You're sort of observing the address of a temporary. That temporary is some proxy object that provides mutable access to a single bit in your collection.

I say "sort of" because you're not even really taking the address; said proxy object has an operator& that gives you something called a "bit iterator" in some implementations.
3. prvalue değişkenin işaret ettiği vector'ün yok olması
Scott Meyers'in "Effective Modern C++" kitabında şöyle bir örnek veriliyor. Örnekte features() metodu rvalue bir vector<bool> döndürüyor. Aşağıdaki kod sorunsuzdur çünkü rvalue vector'ün 5. elamanı bool'a çevrilerek saklanır.
std::vector<bool> features(const Widget& w);
Widget w;

bool highPriority = features(w)[5];

processWidget(w, highPriority); 
Ancak kodu şöyle yaparsak çalışmaz.
auto highPriority = features(w)[5];
Çünkü std::vector<bool>::reference tipi farklı bir tiptir. Kendi içinde pointer kullanan bir proxy sınıfıdır. Eğer proxy'nin point ettiği vector bellekten silinirse sorun çıkar.
Scott Meyer şöyle bir çözüm öneriyor.
auto highPriority = static_cast<bool>(features(w)[5]);
Daha Kolay Bir Çözüm
Şöyle bir metod tanımlarız.
bool is_high_priority(const Widget& w)
{ return features(w)[5]; }
Daha sonra auto ile bu metodun sonucunu saklarız.
auto highPriority = is_high_priority(w);
İki Vector Nesnesinin Karşılaştırılması
Şöyle yapılabilir.
std::vector<bool> A = {0,1,0,1};
std::vector<bool> B = {0,0,1,1};
std::vector<bool> C(A.size());
std::transform(A.begin(), A.end(), B.begin(), C.begin(), 
               [](bool const &a, bool const &b) { return a == b;});
std::cout << std::count(C.begin(), C.end(), true) << std::endl;
Diğer Seçenekler
Kendi veri yapımızı kullanabiliriz.
class Bool
{
public:

  Bool(): m_value(){}
  Bool( bool value ) : m_value(value){}

  operator bool() const { return m_value;}

  // the following operators are to allow bool* b = &v[0]; (v is a vector here).
  bool* operator& () { return &m_value; }
  const bool * const operator& () const { return &m_value; }

private:

  bool m_value;

};
Şöyle kullanırız.
std::vector<Bool> working_solution(10, false);

working_solution[5] = true;
working_solution[7] = true;