0

I have just done a module on pointers and dynamic memory in C++ and am attempting to complete a personal assignment so that I can practice the concepts. The program manages an array of strings that are names. The goal that I set for myself is that the list is stored in the heap (to practice using "new"), and the list is dynamically sized as new names are entered.

Disclaimer: I realize that this is easily accomplished using vectors, and after struggling with this for hours I re-wrote my original code to use a vector for the list with no problems. However I want to learn where my understanding of how pointers work is broken.

The problem that I have with the program is this: I initialize the name array to have zero elements and have a function to add names that handles the dynamic sizing. When first called it seems to re-size the array correctly and add a new name to the the new array. Within the function to add a name, I can print the contents of the new array. I can also re-assign the old array pointer to the address of the new array on the heap. However when I call the print function from main after adding a name to the list, the list does not contain a name. By my understanding, since I'm using pointers I should be updating values directly, so after the add name function terminates, the values should persist. Also, if I attempt to add a second name the program crashes. What am I doing wrong with the handling of memory?

I've searched quite a bit and the closest that I can find for a resolution was this post:

How to make an array with a dynamic size? General usage of dynamic arrays (maybe pointers too)?

I modified my code based on what I understand from that but it still doesn't work properly.

    #include <stdio.h>
    #include <vector>
    #include <iostream>

    using namespace std;

    void add_name_to_list(string * my_list, size_t * list_size);
    string get_name();
    void print_names(const string *const my_list, const size_t *const list_size);

    int main()
    {
        string *name_list_ptr {nullptr};
        name_list_ptr = new string [0];
        size_t name_list_size{0};
        size_t *name_list_size_ptr {&name_list_size};

        print_names(name_list_ptr, name_list_size_ptr);
        add_name_to_list(name_list_ptr, name_list_size_ptr);
        print_names(name_list_ptr, name_list_size_ptr);
        return 0;
    }

    void add_name_to_list (string * my_list, size_t *list_size)
    {
        string new_name{get_name()};
        string *new_string_ptr{nullptr};
            new_string_ptr = new string [*list_size+1];
            // copy existing list into new list
            cout << "List size is " << *list_size << " so *list size == 0 is " << (*list_size == 0) << endl;
            if(*list_size == 0)
            {
                new_string_ptr[0] = new_name;
                *list_size = *list_size +1;
                cout << new_string_ptr[0] << " has been added to position " << *list_size << endl;

            }
            else
            {
                print_names(my_list, list_size);
                for(size_t i{0}; i < *list_size; i++)
                {
                    cout << "At position " << i << " original list is " << my_list[i] << endl;
                    new_string_ptr[i] = my_list[i];
                    cout << "The name " << new_string_ptr[i] << " has been added to position " << i << " of the new list" << endl;
                }
                new_string_ptr[*list_size - 1] = new_name;
                *list_size = *list_size + 1;
            }
            print_names(new_string_ptr, list_size);

            string *temp_ptr{nullptr};
            temp_ptr = new string [*list_size-1];
            cout << "temp ptr is " << temp_ptr << " and my list is " << my_list << endl;
            temp_ptr = my_list;
            cout << "temp ptr is " << temp_ptr << " and my list is " << my_list << endl;
            my_list = new_string_ptr;
            delete [] temp_ptr;
            new_string_ptr = nullptr;
            print_names(my_list, list_size);
    }

    string get_name()
    {
        cin.sync();
        cin.clear();
        string new_name{};
        cout << "\nEnter the full name: ";
        getline(cin, new_name);
        cin.sync();
        cin.clear();
        if(new_name.size() <= 1)
            return "0";
        else
            return new_name;    
    }

    void print_names(const string *const my_list, const size_t *const list_size)
    {
        if(*list_size == 0)
            cout << "The list is empty" << endl;
        else
            for(size_t j{0}; j < *list_size; j++)
                    cout << j << ". " << my_list[j] << endl;
    }

One variation that I've tried based on what I learned from searching is:

    cout << "temp ptr is " << temp_ptr << " and my list is " << my_list << endl;
    //my_list = new_string_ptr;
    //delete [] temp_ptr;
    //new_string_ptr = nullptr;

    delete [] my_list;
    my_list = new string[*list_size];
    my_list = new_string_ptr;
    print_names(my_list, list_size);

Unfortunately the results are the same.

3
  • name_list_ptr = new string [0]; allocates an array of zero size. There's not that much you can do with such an object. You can safely delete a nullptr, so I'd save the trouble of allocating and having to delete an unusable allocation and just leave name_list_ptr pointing at nullptr. Commented Nov 9, 2018 at 0:05
  • When I am faced with a problem like this and I cannot use a std::vector I write a simple poor-man's vector. Getting even a simple mock vector working is quite educational and well worth the time invested. Commented Nov 9, 2018 at 0:11
  • @user4581301 Unfortunately I haven't gotten to making object classes yet, so that's going to take a little while. This implementation is actually the pre-cursor to that. Commented Nov 9, 2018 at 3:26

1 Answer 1

1

Without checking the logic of the implementation, your list doesn't update because you are assigning my_list = new_string_ptr; but your function received void add_name_to_list (string * my_list, size_t *list_size).

As you are newcomer to C++ world, let me explain clearly: list_size is a pointer to a size_t, so if you modify the pointed memory, the change will persist, but if you modify the pointer itself, it will not.

list_size = new size_t; // This change doesn't persist
list_size++; // This change doesn't persist

*list_size++; // This change persists and the value of pointed memory was increased.

With my_list is happening exactly the same, you are trying to modify the pointer itself, not the pointed memory.

So, you should use:

void add_name_to_list (string * &my_list, size_t *list_size)

Or maybe you are more confortable with

void add_name_to_list (string ** my_list, size_t *list_size)
[...]
*my_list = new_string_ptr;

Hope this helps

Sign up to request clarification or add additional context in comments.

5 Comments

Supplementary detail to but if you modify the pointer itself, it will not. The object pointed at is passed by reference (thanks to the pointer) but the pointer itself is passed by value. list_size contains a copy of the address provided by the caller, and changing the copy has no effect on the source.
Exactly. I didn't want to provide too much detail to don't overflow him with terminology.
It's a worthwhile concern, but I think we can get away with it here in the comments.
@LuisGP Thanks for that! I didn't realize that as an object/container pointers could be passed by reference or value... although now that I'm typing that out loud it makes sense. Now that it's working I found another error because I was incrementing the list size too late so I had to move that line of code a couple of lines up. I haven't seen the double asterix before. I'll have to try that.
@AEdwardo Please, consider accept my answer as the solution to your question. Accepting correct answers helps to stackoverflow to grow and makes the community stronger :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.