[英]C++ Function Alters Value of Passed Parameter
我有一个简单的交换函数来获取一个整数数组,并返回一个带有交换值的新数组。
int* Node::dataSwap(int *data, int n_index, int swap_index){
printDatt(data);
int *path = data;
int swapped = data[n_index];
int to_swap = data[swap_index];
path[n_index] = to_swap;
path[swap_index] = swapped;
printDatt(data);
return path;
}
但是,此函数正在更改对原始数据的引用。 输出看起来像这样(打印应该是相同的数据到控制台)。
0, 1, 2
3, 4, 5
6, 7, 8
0, 1, 2
3, 4, 8
6, 7, 5
为什么“数据”在我不更改的情况下会被更改? “路径”是对“数据”实际内存地址的引用吗?
参数data
和局部变量path
是int *
。 您可以将其读作“指向 int 的指针”。
指针是保存内存地址的变量。 不多也不少。 由于您设置了path = data
,这两个指针是相等的。
在您看来, data
是一个数组。 但这不是函数dataSwap
所看到的。 对于函数dataSwap
,它的参数data
只是一个指向 int 的指针。 这个 int 是数组的第一个元素。 您使用data[n_index]
访问了数组的元素; 但这只是*(data + n_index)
的同义词。
如何解决您的问题?
malloc
和memcpy
既然要返回一个新数组,就应该返回一个新数组。 为此,您应该使用malloc
分配一个新的内存区域,然后使用memcpy
将原始数组的值复制到新的内存区域。
请注意,仅使用函数的当前参数是不可能做到这一点的,因为这些参数都没有指示数组的大小:
data
是指向数组第一个元素的指针;n_index
是数组中元素之一的索引;swap_index
是数组中另一个元素的索引。* 因此,您应该向函数中添加第四个元素int size
,以指定数组中有多少个元素。 您可以使用size
作为malloc
和memcpy
参数,或者编写一个 for 循环遍历数组的元素。
新问题出现:如果你调用malloc
来分配新的内存,那么用户将不得不在某个时刻调用free
来释放内存。
C++ 有很酷的关键字new
它的语法比malloc
的语法要轻一些。 但这并不能解决主要问题; 如果您使用关键字new
分配新内存,那么用户将不得不在某个时候使用关键字delete
释放内存。
呃,好大的负担!
但这是C方式。 C++ 中的一个很好的经验法则是:永远不要手动处理数组。 标准库为此提供了std::vector
。 在某些情况下,使用new
可能是最好的解决方案; 但在大多数简单的情况下,事实并非如此。
std::vector
使用标准库中的std::vector
类,您的代码变为:
#include <vector>
std::vector<int> Node::dataSwap(std::vector<int> data, int n_index, int swap_index)
{
std::vector<int> new_data = data;
int swapped = data[n_index];
int to_swap = data[swap_index];
new_data[n_index] = to_swap;
new_data[swap_index] = swapped;
return (new_data);
}
没有malloc
,没有new
,没有free
也没有delete
。 类std::vector
在内部处理所有这些。 您也不需要手动复制数据; 初始化new_data = data
调用类std::vector
的复制构造函数并为您执行此操作。
尽量避免使用new
; 使用一个在内部处理所有内存的类,就像您在高级语言中所期望的那样。
或者,更简单:
std::vector
和std::swap
#include <vector>
#include <algorithm>
std::vector<int> Node::dataSwap(std::vector<int> data, int n_index, int swap_index)
{
std::vector<int> new_data = data;
std::swap(new_data[n_index], new_data[swap_index]);
return (new_data);
}
“路径”是对“数据”实际内存地址的引用吗?
是的! 为了创建一个作为传递数据副本的新数组(仅交换一对值),那么您的函数需要创建新数组(即为其分配数据),复制传递的数据进入它,然后执行交换。 然后,该函数将返回该新数据的地址,当不再需要时,该地址应在稍后释放。
但是,为了做到这一点,您还需要将数据数组的大小传递给函数。
使用“旧式”C++ 的一种方法是使用new
运算符。 添加“大小”参数后,您的函数将如下所示:
int* Node::dataSwap(int *data, int n_index, int swap_index, int data_size)
{
printDatt(data);
int *path = new int[data_size]; // Create new array...
for (int i = 0; i < data_size; ++i) path[i] = data[i]; // ... and copy data
int swapped = data[n_index];
int to_swap = data[swap_index];
path[n_index] = to_swap;
path[swap_index] = swapped;
printDatt(data);
return path; // At some point later on, your CALLING code would "delete[] path"
}
您正在更改指针路径指向的内存,即data 。 我认为尝试更好地了解指针的工作原理会对您有所帮助。 :)
然后你可以使用 std 库中的交换函数:
std::swap(data[n_index], data[swap_index]);
它会让你的代码更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.