Here you can refresh your memory about pointer.
Pointer and Reference
Pretty basic, Right ?  
int a = 1234;
int *pa = &a;    // pa is pointer of a
*pa = 1111;      // assignment on *pa will change a also
int &ra = a;     // ra is reference of a
ra = 4321;       // assignment on ra will change a also
Function return value using reference or pointer
Which do you prefer ?  * or & ? 
int AddAndMultiply(int a, int b, int& mult)
{
  mult = a * b;
  return a + b;   
}
int AddAndMultiplyV3(int a, int b, int* mult)
{
  *mult = a * b;
  return a + b;
}
int mult = 0;
int sum = AddAndMultiply(1, 2, mult);
sum = AddAndMultiplyV3(1, 2, &mult);
Function return struct
I can read this easily. But isn't struct make code slow by copying memory ? Are you sure ? 
struct AddMult
{
  int Add;
  int Mult;
};
AddMult AddAndMultiplyV3(int a, int b)
{
  AddMult r;
  r.Add = a + b;
  r.Mult = a * b;
  return r;
}
AddMult r = AddAndMultiplyV3(1, 2);
sum = r.Add;
mult = r.Mult;
const at before or after
const int* cpa = &a;
*cpa = 42;           // compile error : cpa is pointing a constant variable, so you can't change the value
cpa = &b;            // but you can make it points other variable
const int& cra = a;
cra = 42;            // compile error : cra is referencing a constant variable, so you can't change the value
int* const pca = &a; 
*pca = 42;           // no problem : pca is constantly pointing a variable, and you can change the value of variable.
*pca = &b;           // compile error : but pca can't pointing to other variable.
mutable can be changed on const method
Then what's the point of const if there is mutable ?
struct AddData
{
  int A, B;
  mutable int C = 0;  // ok to be changed on const method.
  int AddAll() const  // This isn't supposed to change member variable. 
  {
    if (C == 0) { C = A + B; }
    return C;
  }
};
Endianess
big-endian puts significant bytes at lower address, while little-endian puts significant bytes at higher address.
uint32_t *pa = new uint32_t[4];
pa[0] = 0x12345678;     // note the little-endian
pa[1] = 0x87654321;
pa[2] = 0x10101010;
pa[3] = 0xCAFEBEEF;
*pa = 0xFFFFFFFF;
*(pa + 1) = 0xEEEEEEEE;
delete[] pa;
64 bit ponter
Each pointer is 64bits.
Packing at struct
Do you know how variable is packed in a struct ? 
struct Foo
{
  uint32_t a;     // 4 Bytes
  char b;         // 2 Bytes
  uint16_t c;     // 2 Bytes
  bool d;         // 4 Bytes
  const char * e; // 4 Bytes
};
Foo foo;
Foo* pfoo = &foo;
foo = { 0x12345678, 'a', 0xCAFE, true, nullptr };
Function pointer
This syntax of putting type name in between retrun type and argument type and *, (, ). Can you remember it ?   
int TestBar(char a) {  return a + 42;  }
int TestToo(char a) {  return a + 22;  }
typedef int(*FooFn)(char);  // Here you go!
FooFn f = TestBar;
int ret = f('a');
f = TestToo;
ret = f('b');
STL function pointer
Or how about STL style ?
int TestBar(char a) {  return a + 42;  }
int TestToo(char a) {  return a + 22;  }
using FooFn = std::function< int(char) >;  // Here you go again !
FooFn fn = TestBar;
int ret = fn('a');
fn = TestToo;
ret = fn('b');