What is the Stack

beginner c++11 memory

All variables in C++ use a portion of the memory of your computer. C++ has two basic forms of memory: the stack and the heap. The stack is where local variables are stored in memory. Local here means “in the current scope” and a scope is defined as the code between curly braces ({}). Every time a new scope is created C++ uses a portion of the stack to store that scope’s local variables and if it’s a function its parameters and return value. Because C++ has pointers we can print the addresses of stack variables and confirm for ourselves they are using different pieces of memory. Here’s an example of scopes and stack variables:

#include <iostream>

void foo(int a) {
  std::cout << "      foo() Scope\n";
  int b = 4;
  std::cout << "      a: " << a << ", &a: " << &a << "\n";
  std::cout << "      b: " << a << ", &b: " << &b << "\n";
  std::cout << "      leaving foo() Scope\n";
}

int main() {
  std::cout << "Main Scope\n";
  int a = 10;
  std::cout << "a: " << a << ", &a: " << &a << "\n";

  {
    std::cout << "  First Inner Scope\n";
    int b = 20;
    std::cout << "  a: " << a << ", &a: " << &a << "\n";
    std::cout << "  b: " << b << ", &b: " << &b << "\n";

    {
      std::cout << "    Second Inner Scope\n";
      int c = 30;
      std::cout << "    a: " << a << ", &a: " << &a << "\n";
      std::cout << "    b: " << b << ", &b: " << &b << "\n";
      std::cout << "    c: " << a << ", &c: " << &c << "\n";

      foo(a);

      std::cout << "    Leaving Second Inner Scope\n";
    }

    std::cout << "  a: " << a << ", &a: " << &a << "\n";
    std::cout << "  b: " << b << ", &b: " << &b << "\n";
    std::cout << "  Leaving First Inner Scope\n";
  }
  std::cout << "a: " << a << ", &a: " << &a << "\n";
  std::cout << "Leaving Main Scope\n";
}
Main Scope
a: 10, &a: 0x7ffeef0106ac
  First Inner Scope
  a: 10, &a: 0x7ffeef0106ac
  b: 20, &b: 0x7ffeef0106a8
    Second Inner Scope
    a: 10, &a: 0x7ffeef0106ac
    b: 20, &b: 0x7ffeef0106a8
    c: 10, &c: 0x7ffeef0106a4
      foo() Scope
      a: 10, &a: 0x7ffeef01068c
      b: 10, &b: 0x7ffeef010688
      leaving foo() Scope
    Leaving Second Inner Scope
  a: 10, &a: 0x7ffeef0106ac
  b: 20, &b: 0x7ffeef0106a8
  Leaving First Inner Scope
a: 10, &a: 0x7ffeef0106ac
Leaving Main Scope

Automatic Memory Management

Explicit management of the stack is not necessary in your program and is automatic in C++. Automatic memory management of scopes and local variables is one of the many things your compiler is doing for you when your code is compiled into a complete program. If you’re familiar with destructors you’ll remember that C++ always calls object destructors when that object is leaving the scope it’s in. That’s because the stack memory of that object is about to be reclaimed and reused for the next scope and so the object must be cleaned up. Here’s an example:

#include <iostream>

class Talker {
public:
  explicit Talker(std::string name) : name_(std::move(name)) {
    std::cout << name_ << " here.\n";
  }
  ~Talker() {
    std::cout <<  name_ << ", signing off.\n";
  }
private:
  std::string name_;
};

int main() {
  std::cout << "Main Scope\n";
  Talker jose("Jose");
  std::cout << "&jose: " << &jose << "\n";

  {
    std::cout << "  First Inner Scope\n";
    Talker nushi("  Nushi");
    std::cout << "  &nushi: " << &nushi<< "\n";
    std::cout << "  Leaving First Inner Scope\n";
  }
  std::cout << "Leaving Main Scope\n";
}
Main Scope
Jose here.
&jose: 0x7ffee85f8698
  First Inner Scope
  Nushi here.
  &nushi: 0x7ffee85f8658
  Leaving First Inner Scope
  Nushi, signing off.
Leaving Main Scope
Jose, signing off.

Variable Shadows

When new scopes are created variables from outer scopes can still be used, but they can also be shadowed meaning their names can be reused.

#include <iostream>

int main() {
  int a = 4;
  std::cout << "a: " << a << ", &a: " << &a << "\n";

  {
    // Assign to the same "a" from outer scope
    a = 8;
    std::cout << "  a: " << a << ", &a: " << &a << "\n";

    {
      // *Shadow* the outer scope's "a", create a new "a"
      int a = 12;
      std::cout << "    a: " << a << ", &a: " << &a << "\n";
    }

    std::cout << "  a: " << a << ", &a: " << &a << "\n";
  }
  std::cout << "a: " << a << ", &a: " << &a << "\n";
}
a: 4, &a: 0x7ffeecb9d6ac
  a: 8, &a: 0x7ffeecb9d6ac
    a: 12, &a: 0x7ffeecb9d6a8
  a: 8, &a: 0x7ffeecb9d6ac
a: 8, &a: 0x7ffeecb9d6ac

For more C++ By Example, click here.