c++variablesreference

Variable as reference not staying


I read this thread and many others: Function does not change passed pointer C++

Yet I still can't solve my issue. I have a function declared like this:

void test(list<int*> *listNodes){
    int v=5;
    (*listNodes).push_back(&v);
    (*listNodes).push_back(&v);
    (*listNodes).push_back(&v);
    for(int a = 0; a < (*listNodes).size(); a ++){
        std::list<int*>::iterator i = (*listNodes).begin();
        advance(i, a);
        int *totry = *i;
        cout << *totry;
        cout << ",";
    }
}

Which works, and prints fine, by the I mean: the listNodes variable has 3 elements, all 5's. However, when this functions returns, the values are not updated. By that, I mean that the variable has trash. I call this function in another one like this:

void create(list<int*> listNodes){
    test(&listNodes);
    for(list<int*>::const_iterator it=listNodes.begin();
     it!=listNodes.end(); it++){
        int *show=*it;
        cout << *show << '\n';
    }
}

Again, in this function, the cout will output memory garbage instead of outputting the 3 fives. Any ideas on how should I proceed to, when the function test comes back, I have the list populated?


Solution

  • The problem I believe you're thinking about (as opposed to other problems in this code) is not actually what you're thinking. The list DOES maintain its values, the problem is that the values it has are pointing to garbage memory.

    When you do this:

    int v=5;
    (*listNodes).push_back(&v);
    (*listNodes).push_back(&v);
    (*listNodes).push_back(&v);
    

    You are putting three copies of the address of v into the list. You have declared v as a stack variable that only exists for the duration of this function. When you print the values pointed to by the elements of listNodes inside function test, that variable still exists in that memory location.

    When you later print out the values pointed to by the elements of listNodes in function create, that variable has gone out of scope and has been used by something else, hence the garbage.

    Here are two possible solutions to consider:

    1. Use list<int> instead of list<int *>. If all you want to do is store a list of integers, this is the way to go.
    2. If, on the other hand, you really need to store pointers to those integers, you'll need to allocate memory off the heap:

      int* v = new int(); // allocate an int on the heap
      *v = 5;             // store 5 in that int
      (*listNodes).push_back(v);  // save the pointer to the allocated
                                  // memory in *listNodes
      etc
      

    This is not very good in terms of modern c++, however, as you generally don't want to be handling raw pointers at all, but it illustrates the point I think you are struggling with.