c++ - C ++在不同函数中重新分配指向动态内存中数组的指针
问题描述
我刚刚在 C++ 中完成了一个关于指针和动态内存的模块,并且正在尝试完成一项个人作业,以便我可以练习这些概念。该程序管理一个名称字符串数组。我为自己设定的目标是将列表存储在堆中(练习使用“new”),并且在输入新名称时动态调整列表的大小。
免责声明:我意识到使用向量很容易实现这一点,在为此苦苦挣扎了几个小时后,我重新编写了原始代码以将向量用于列表,没有任何问题。但是,我想了解我对指针工作原理的理解在哪里被破坏了。
我在程序中遇到的问题是:我将名称数组初始化为具有零个元素,并具有添加处理动态大小的名称的函数。首次调用时,它似乎正确地重新调整了数组的大小并向新数组添加了一个新名称。在函数内添加名称,我可以打印新数组的内容。我还可以将旧数组指针重新分配给堆上新数组的地址。但是,当我在将名称添加到列表后从 main 调用打印函数时,列表不包含名称。据我了解,由于我使用的是指针,我应该直接更新值,所以在添加名称函数终止后,值应该保持不变。此外,如果我尝试添加第二个名称,程序会崩溃。我在处理内存方面做错了什么?
我已经搜索了很多,我能找到的最接近的解决方案是这篇文章:
如何制作具有动态大小的数组?动态数组的一般用法(也可能是指针)?
我根据我的理解修改了我的代码,但它仍然无法正常工作。
#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;
}
根据我从搜索中学到的知识,我尝试过的一种变体是:
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);
不幸的是,结果是一样的。
解决方案
如果不检查实现的逻辑,您的列表不会更新,因为您正在分配my_list = new_string_ptr;
但您的函数收到了void add_name_to_list (string * my_list, size_t *list_size)
。
由于您是C++世界的新手,让我解释清楚:list_size是指向size_t的指针,因此如果您修改指向的内存,则更改将持续存在,但如果您修改指针本身,则不会。
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.
my_list
发生的情况完全相同,您正在尝试修改指针本身,而不是指向的内存。
所以,你应该使用:
void add_name_to_list (string * &my_list, size_t *list_size)
或者也许你更舒服
void add_name_to_list (string ** my_list, size_t *list_size)
[...]
*my_list = new_string_ptr;
希望这可以帮助
推荐阅读
- python-3.x - 如何在 if...else 中匹配所有内容?
- laravel - 错误:在 laravel 的 UserController 中创建新用户时的 array_key_exists()
- javascript - 在 Node.js 中使用 htmlparser2 选择 html 节点的文本内容
- java - Hibernate Search java spring,仅搜索具有指定ID的实体
- php - Laravel 该路由不支持 GET 方法。支持的方法:POST
- php - 从打印 json_encode 添加逗号
- python - django postgresql tests.py RuntimeWarning 错误
- django - Django Rest Api - ManyToManyField,在练习数组中显示'title'而不是'id'
- javascript - 生成txt文件的头文件
- laravel-5 - 更改现有 Laravel 集合键的值