Question about address in the pointer mémoria

Asked

Viewed 56 times

3

I put a Cout in the way insertRight to verify the memory addresses of node1 (of the variable itself and not of what she keeps) and to my surprise the addresses shown repeated several times, as shown below.

004FF97C
004FF97C
004FF894
004FF97C
004FF894
004FF7AC
004FF97C
004FF894
004FF7AC
004FF6C4

Note that one of the local pointers has the same address in two consecutive calls to function insertRight

Because they are local pointers and therefore local variables (I believe, am I right?) , they should not be destroyed at the end of the method execution and be allocated to another memory address in the stack in a future call ?

Code:

Nodetree. h

class NodeTree
{
public:
    int value;
    NodeTree *right;
    NodeTree *left;

    NodeTree() {
        value = 0;
    }
};

Binarytree. h

#include <iostream>
using std::cout;
using std::endl;
#include "NodeTree.h"


class BinaryTree
{
public:
    NodeTree * root;
    BinaryTree();
    void insert(int);
    void insertRight(NodeTree *, NodeTree **);
};

Binarytree.cpp

#include "BinaryTree.h"

BinaryTree::BinaryTree() {
    root = NULL;
}

void BinaryTree::insert(int num) {

    NodeTree *node = new NodeTree;
    node->value = num;
    insertRight(node, &root);
}

void BinaryTree::insertRight(NodeTree *node1, NodeTree **root1)
{
    cout << &node1 << endl;

    if (*root1 == NULL) {
        node1->left = NULL;
        node1->right = NULL;
        *root1 = node1;
    }
    else {
        insertRight(node1, &(*root1)->right);
    }
}

Teste_pointers.cpp

#include "BinaryTree.h"

int main()
{   
    BinaryTree tree;
    tree.insert(5);
    tree.insert(10);
    tree.insert(15);
    tree.insert(20);
    tree.printInOrder(tree.root);
    return 0;
}

1 answer

2


Starting with the first statement you made:

and to my surprise the address shown repeated several times

This is expected for the code you have, the insertRight, 'cause every time you’re about to make an insertion, you start at the root and navigate right until you catch a zero. Soon it will start 4 times to navigate through the root, causing the root node to be shown 4 times. If you had placed a visual separator between each insertion as a \n it would have been easier to interpret the result.

See the impression you have, identifying each node and each insert:

004FF97C //insert 1 raiz
004FF97C //insert 2 raiz
004FF894 //insert 2 raiz->direita
004FF97C //insert 3 raiz
004FF894 //insert 3 raiz->direita
004FF7AC //insert 3 raiz->direita->direita
004FF97C //insert 4 raiz
004FF894 //insert 4 raiz->direita
004FF7AC //insert 4 raiz->direita->direita
004FF6C4 //insert 4 raiz->direita->direita->direita

Let us now turn to the question you raised later:

Because they are local pointers and therefore local variables (I believe, am I right?) they should not be destroyed at the end of the method execution and have other addresses in a future call ?

Pointers are local but the created object is not, and can confirm this by creating with the operator new that allocates memory in the heap and not in the stack:

void BinaryTree::insert(int num) {

    NodeTree *node = new NodeTree;

So objects are allocated in memory and keep the same address until they are destroyed with the operator delete. The local pointer NodeTree *node which he created is destroyed but the object to which he points is not, so he can access it with any other pointer pointing to the same location.

Even you keep that pointer in a field of your class when you do *root1 = node1; within the function insertRight.

Also note that if it was not allocated with the new the object would be destroyed at the end of the function, but this already made its code incorrect and presenting undefined behavior, and that with bad luck could even work. So if you’re going to use objects you created in a function somewhere else you need them to be allocated in the heap through the new.

  • I got a little confused. This means that if a local pointer is destroyed after the method is executed, the next local pointer that is created in a later method call will have the same memory address (I don’t mean the memory address that is stored as value, but the pointer’s own address) that the previous pointer ? Because the given answer seemed to refer not to the address of the pointer itself but to the address it stores of another element

  • 1

    @Rogi93 "It means that if a local pointer is destroyed after the execution of the method, the next local pointer that is created in a later method call will have the same memory address" - In the beginning no but we have no way of saying, since we don’t manage address assignment, and it can happen by coincidence, but it’s not supposed to affect our code. The answer actually refers to the address it stores and not the variable itself. It is important to realize that when you do NodeTree *node = new NodeTree; is actually creating two things, which are: 1) An object in a place [...]

  • 1

    [...] in memory defined by heap allocator 2) A pointer that points to that object and therefore receives the object address as its value. At the end of the function only the pointer is discarded, ie the local variable. The memory space that was allocated remains unchanged with the data that has been placed there

  • Why my doubt refers to the address of the pointer itself, which is different from the address it stores as value.

  • 1

    @Rogi93 This is another detail that is confusing. What you are printing is the address of a function parameter - cout << &node1, in which node1 is the parameter and not a variable you created locally. And this parameter comes from a pointer you previously saved in the tree with *root1 = node1 soon the addresses will not change as they are stored in the tree. You saved each of the pointers in the tree.

  • I get it. In my case, I could never get the address of the pointer itself, because the return address will always be from the argument passed to the method, correct ?

  • 1

    @Rogi93 No, you can and is showing the pointer address, which in this case is the argument of the function. The detail by which it does not change is because the pointers are stored. Imagine that you have an object in an address and create a pointer for it. If you now store this pointer in a structure, every time you access the pointer address will give the same value as you store it. It would be different to create another pointer that pointed to the same object, in which case the impression of the address would already give a different value (supposedly, we have no way to guarantee).

  • A doubt about that part:"... The detail by which it does not change is because the pointers are stored" this behavior is also valid for a pointer pointing to a simple integer variable of automatic storage ? Ex: int i = 2 ; int *ptr = &i

  • 1

    @Rogi93 Yes works exactly the same way if the ptr is stored in a structure, as in your code. Now there is a significant and serious difference, which is in this example the ptr is pointing to an invalid memory address when the function ends, because the int i will be released at the end of the function (assuming that it is executed within a function that however ends). In his example the pointer was pointing to something allocated with new and so remained valid even after the function ended.

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.