カテゴリー
C++

C++ の文法

C++の文法について、個人的なメモ

Stack vs Heap

Objectをinstantiateする時、メモリをstackとheapどちらからallocateするかによって処理内容と文法が大きく違います。

struct Vector3 {
  float x, y, z;

  Vector3()
    : x(10), y(11), z(12) {}
};

// stack
// int
int value = 5;
// array. allocating 5 * int size in memory
int array[5];
array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4;
array[4] = 5;
// object
Vector3 vector;

// heap
// int
int* hvalue = new int;
*int = 5;
// array
int* harray = new int[5];
harray[0] = 1;
harray[1] = 2;
harray[2] = 3;
harray[3] = 4;
harray[4] = 5;
// object, () is optional
Vector3* hvector = new Vector3();

// you need to manually call delete to deallocate
delete hvalue;
delete[] harray;
delete hvector;

stackにvariableをallocateする時は、”stack pointer”がメモリ上でvariableのサイズだけ移動させ、メモリを次々とallocateする(stack)ので、動作がとても早いです。variableのscopeが終わると自動的にdeallocateされます。

heapの場合はallocateの時newで「free list(メモリ領域にあるavailableなメモリのリスト)」からavailableなメモリブロックを探しだし、確保し、そのpointerをdereferenceした上で、値を代入します。また、明示的に delete(deallocate)する必要があります。もしApplicationに割り当てられた以上のメモリが必要になると、Applicationはsystemに要求します。つまりとても「コストが高い」オペレーションです。

smart pointers の場合は裏でこのnew、deleteが呼ばれています。

可能な限りstackにメモリをallocateする方が良い、ということです。

PointerReference

int a = 5;
int* ptr = &a;
std::cout << *a << std::endl; // prints 5 (value of a)

int& ref = a;  // ref is now an alias of a
ref = 2;
std::cout << a << std::endl; // prints 2

Constructor

このThe Chernoのtutorialで説明されているように、initializer listによるinitializationは、member variableを一度だけinstantiateするため効率が良いです。また、initializer listによるinitializationはinitializer listの順番ではなく、member variableが宣言されている順に実行されるため、dependencies(どのmemberが先にinitializeされなくてはならないか、など)に関して気をつけなければなりません。

class Entity {

public:
  // a constructor without parameter
  Entity {
  }
 // a constructor with initializer lists
  Entity(float x, float y)
    : X(x), Y(y) // it needs to be in the same order as you declared
  {
  }
  // a constructor with parameters
  Entity(float x, float y) {
    X = x;
    Y = y;
  }
  float X, Y;
}

class Log {

public:
  // by assigning delete, can disable default constructor
  Log() = delete;
}

Copy Constructor

// example of deep copy...
class Entity {
public:
  Entity() {} // default constructor
  // copy constructor
  Entity(const Entity& other) {
    m_X = other.m_X;
  }
  int m_X;
}

Smart Pointers

//unique pointer

// shared pointer

// weak pointer

Macro

// example
#define LOG(x) std::cout << x << std::endl

Namespace alias

// example...
using MidiKeyboardStateListener = MidiKeyboardState::Listener;

Const

const int MAX_AGE = 90;
int* a = new int; // a is a pointer
*a = 2; // you can dereference a and assign 2
a = (int*)&MAX_AGE // you can reassign pointer

const int* a = new int; // add "const" keyword to a pointer
// you can also write it as "int const* a"
*a = 2; // error, you can't modify the contents of the pointer
a = (int*)&MAX_AGE; // no error
std::cout << *a << std::endl; // reading a works

int* const a = new int;
*a = 2; // this works
a = (int*)&MAX_AGE; // error
a = nullptr; // error

class Entity {
private: 
  int m_X, m_Y;

public:
  int GetX() const { // it means the function can't modify the value
                     // read only method
                     // good for getters
    m_X = 2;  // can't do this
    return m_X;
  }

  void SetX(int x) {  // can't have const here...
    m_X = x;
  }
}

void PrintEntity(const Entity& e) {
  std::cout << e.GetX() << std::end;  // if I remove const from
                                      // the above GetX(), it won't work
}

const reference

non-const lvalue reference

lvalues and rvalues

lvalueはメモリ上にアドレスがある値(変数など)j

rvalueはメモリ上にアドレスがない値(記述されただけの値)

int i = 5;
int& a = 10;  // this does not work, because 10 is a rvalue
int& b = i; // this works, because i is a lvalue
const int& c = 10; // this works
// it creates a temporary behind the scenes as in the below pseudo code
int temp = 10;
int& c = temp;

Lambda — captureをthis(オブジェクト)でするか、&(オブジェクトのreference)でするか、ですが、referenceの場合はmember変数に変更を加えます。

関数の戻り値へconst keywordをつけると、戻り値はconst(変更不可)になります。

// example
juce::String getCurrentPreset() const;