Question: I am very confused about the const version and non-const version member function like below:

```
value_type& top() { return this.item }
const value_type& top() const { return this.item }

```

What is the difference between these two functions? In what situation would they be used?

Answer: 
In short, they're used to add 'const correctness' to your program.

```
value_type& top() { return this.item }

```

This is used to provide mutable access to `item`. It is used so you can modify the element in the container. 

For example:

```
c.top().set_property(5);  // OK - sets a property of 'item'
cout << c.top().get_property();  // OK - gets a property of 'item'

```

One common example for this pattern is returning mutable access to an element with `vector::operator[int index]`.

```
std::vector<int> v(5);
v[0] = 1;  // Returns operator[] returns int&.

```

On the other hand:

```
const value_type& top() const { return this.item }

```

This is used to provide `const` access to `item`. It's more restrictive than the previous version - but it has one advantage - you can call it on a const object.

```
void Foo(const Container &c) {
   c.top();  // Since 'c' is const, you cannot modify it... so the const top is called.
   c.top().set_property(5);  // compile error can't modify const 'item'.
   c.top().get_property();   // OK, const access on 'item'. 
}

```

To follow the vector example:

```
const std::vector<int> v(5, 2);
v[0] = 5;  // compile error, can't mutate a const vector.
std::cout << v[1];  // OK, const access to the vector.

```
The const-qualified member function will be called if the member function is called on an object that is const-qualified.

The non-const-qualified member function will be called if the member function is called on an object that is not const-qualified.

For example:

```
MyStack s;
s.top(); // calls non-const member function

const MyStack t;
t.top(); // calls const member function

```

Note that the same rules apply when calling a member function on a reference to an object or through a pointer to an object: if the pointer or reference is to a const object, the const member function will be called; otherwise the non-const member function will be called.