我有一个功能
double* get_row(double *the_array, int row_num, int col_size)
其中the_array
是2D数组,row_num
是2D数组上我要从中复制值的行号,而col_size
是2D数组的列大小
功能实现
double* get_row(double *the_array, int row_num, int col_size) {
double* row = new double[col_size];
for (int i = 0; i < col_size; i++) {
*row = *(*(the_array + row_num) + i);
row++;
}
delete[] row;
return row;
}
im试图将值从2D数组row_num
的行the_array
复制到1D数组row
中,但是编译器在一行上给我一个错误
*row = *(*(the_array + row_num) + i);
我曾经将元素从一个数组复制到另一个数组,完成此任务的正确方法是什么。
从Visual Studio得到的错误是:'*'的操作数必须是指针。
感谢您的帮助。
答案 0 :(得分:1)
为了解决这个问题,我假设“ col_size”实际上是“列数”。并且数据按行优先顺序排列。
然后,第N行的开头位于the_array + row_num*col_size
。
我将从这个辅助函数开始:
inline double* view_row_n( double* array, int row, int num_cols ) {
return array+row*num_cols;
}
然后我要写一个复制缓冲区:
std::unique_ptr<double[]> copy_buffer( double const* in, int count ) {
double* retval = new double[count];
std::memcpy( retval, in, sizeof(double)*count );
return std::unique_ptr<double[]>( retval );
}
现在我将它们一起使用:
double* get_row( double* the_array, int row_num, int col_size) {
auto retval = copy_buffer( view_row_n( the_array, row_num, col_size), col_size );
return retval.release();
}
并完成它。
我还要更改:
double* get_row( double const* the_array, int row_num, int col_size) {
甚至:
std::unique_ptr<double[]> get_row( double const* the_array, int row_num, int col_size) {
但这超出了您的问题范围。
答案 1 :(得分:1)
如果get_row
不需要您将新的内存分配回调用方,则解决方案将简单地是
double* get_row(double *the_array, int row_num, int col_size)
{
return the_array + (row_num * col_size);
}
如果希望调用者将新的内存分配给返回的行,则
double* get_row(double *the_array, int row_num, int col_size)
{
double* row = new double[col_size];
for(int i = 0; i < col_size; i++)
row[i] = *(the_array + (row_num * col_size) + i);
return row;
}
会工作的。
在第一个解决方案中,想法是使用row_num * col_size
到达正确的行,并简单地返回该地址位置作为结果。在第二个解决方案中,我们首先声明一个新行。然后使用i
索引该行中的每个元素,并复制the_array
所在行中的the_array + (row_num * col_size)
的每个元素。
答案 2 :(得分:0)
这不是现代的C ++,显然您不应该删除返回值。
im试图从2D数组the_array的行row_num复制值 进入一维数组
首先,在这种情况下,the_array
被定义为原始指针,并用于指针算术,是2D数组的1D表示形式-在我们的描述中最好是准确的
我得到[...]的错误是:'*'的操作数必须是一个指针
好,所以这一行:
*row = *(*(the_array + row_num) + i);
有点混乱。我想我知道您要使用它了,但是您正在取消引用(使用表达式左侧的*
)两次 ,哪个BTW会导致错误。还记得我们说过the_array
是原始指针,被视为一维数组。因此,您可以使用这种类型的指针算法,例如在括号内说,然后仅对其取消引用一次。上面的表达式使用结果地址(the_array + row_num)
,对其进行解引用以在数组的此单元格中获取double
,然后将i
添加到double
值中本身,然后尝试取消引用double
和int i
的总和-这是类型为double
的临时变量,一个指针。这可能是您要针对的行:
*row = *(the_array + row_num * col_size + i);
由于2D数据在内存中具有传染性,连续逐行传播,因此您需要将行索引乘以这样的行大小(也就是列数,并且我认为col_size
实际上就是这样,否则您将无法在行之间遍历)以“在行之间跳过” ,最后添加当前单元格索引i
来获得行内的特定单元格。然后,就像我们说的那样,取消对整个事物的引用。
除了编译问题和地址计算之外,您还应至少保留row
的地址,然后再在循环中递增它,以便可以返回它,而不是返回该行末尾的指针。 为了尽可能多地保留原始功能,您可以使用第二个指针来做到这一点:
double* get_row(double *the_array, int row_num, int col_size) {
double* row = new double[col_size];
double* rowPtr = row;
for (int i = 0; i < col_size; i++) {
*rowPtr = *(the_array + row_num * col_size + i);
rowPtr++;
}
return row;
}
我正在尝试使其尽可能接近您的版本,因此您可以看到与您所做的不同。许多事情最好以不同的方式完成,例如,为什么不首先使用[]
这样的row[i] = *(the_array + row_num * col_size + i);
运算符,然后完全摆脱第二个指针?如果您原样遍历++
,则实际上不需要在循环中第二行进行i
。另一个例子是您是否必须分配,还是可以将指针返回到现有数组,但是在正确的位置?
重要的是这里几乎没有提到,您真的不应该这样返回原始指针,因为它很容易导致代码中的意图不明确,例如谁拥有分配(并最终负责删除分配),并提出了在异常情况下如何防止内存泄漏的问题?首选的解决方案是使用智能指针such as std::unique_ptr
,该实例的一个实例包装原始指针并使之指向原始指针,因此如果您只想扔掉那部分内存,则必须非常明确
答案 3 :(得分:0)
double* get_row(double *the_array, int row_num, int col_size) {
double* row = new double[col_size];
for (auto i = 0; i < col_size; ++i) {
row[i] = the_array[row_num * col_size + i];
}
// If the return isn't assigned, the program will leak!
return row;
}
void row_test() {
double two_d[15];
const auto row = get_row(two_d, 2, 5);
// ...
// Be sure to delete row afterwards
delete[] row;
}