数组作为c ++中的out参数

时间:2013-06-27 01:53:56

标签: c++ arrays pass-by-pointer

我创建了一个返回错误代码(ErrCode枚举)并传递两个输出参数的函数。但是当我打印函数的结果时,我没有在数组中得到正确的值。

// .. some codes here ..
ErrCode err;
short lstCnt;
short lstArr[] = {};
err = getTrimmedList(lstArr, &lstCnt);

// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
 printf("lstArr[%3d] = %d", i, lstArr[i]);
// .. some codes here ..

getTrimmedList函数是这样的:

ErrCode getTrimmedList(short* vList, short* vCnt)
{
  short cnt;
  ErrCode err = foo.getListCount(FOO_TYPE_1, &cnt);
  if (NoError!=err) return err;

  short* list = new short [cnt];

  short total = 0;
  for (short i=0; i<cnt; ++i)
  {
    FooBar bar = foo.getEntryByIndex(FOO_TYPE_1, i);

    if (bar.isDeleted) continue;

    list[total] = i;
    ++total;
  }

  *vCnt = total;
  //vList = (short*)realloc(index, sizeof(short)*total);
  vList = (short*)malloc(sizeof(short)*total);
  memcpy(vList, list, sizeof(short)*total)

  // list returned array (for comparison)
  for (int i=0; i<lstCnt; ++i)
   printf("lstArr[%3d] = %d", i, lstArr[i]);

  return NoError;
}

其中:

  • foo是一个包含FooBar个对象
  • 数组的对象
  • foo.getListCount()返回类型为FOO_TYPE_1
  • 的对象数
  • FOO_TYPE_1是我们要采取的对象类型/列表
  • foo.getEntryByIndex()返回类型为i
  • FooBar FOO_TYPE_1个对象
  • bar.isDeleted是一个标志,告知bar是否被视为“已删除”

我的错误是什么?

修改

抱歉,我复制了错误的一行。我在上面评论了它,并把正确的行。

修改2

我无法控制foobar的回报。它们的所有函数返回都是ErrCode,输出通过参数传递。

3 个答案:

答案 0 :(得分:1)

在我回答你的帖子之前,有几个问题......

“index”在哪里定义: vList = (short*)realloc(index, sizeof(short)*total);

您是否泄漏与以下相关的内存: short* list = new short [cnt];

您是否有可能在内存分配中意外混淆了指针?无论如何,这里有一个例子。您遇到了许多问题,但您应该可以将其作为指导来回答最初提出的问题。

工作示例:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

int getTrimmedList(short** vList, short* vCnt);

int main ()
{
  // .. some codes here ..
  int err;
  short lstCnt;
  short *lstArr = NULL;
  err = getTrimmedList(&lstArr, &lstCnt);

  // list returned array (for comparison)
  for (int i=0; i<lstCnt; ++i)
    printf("lstArr[%3d] = %d\n", i, lstArr[i]);
  // .. some codes here ..

  return 0;
}

int getTrimmedList(short** vList, short* vCnt)
{
  short cnt = 5;
  short* list = new short [cnt];
  short* newList = NULL;

  short total = 0;
  list[0] = 0;
  list[1] = 3;
  list[2] = 4;
  list[3] = 6;
  total = 4;

  *vCnt = total;
  newList = (short*)realloc(*vList, sizeof(short)*total);
  if ( newList ) {
    memcpy(newList, list, sizeof(short)*total);
    *vList = newList;
  } else {
    memcpy(*vList, list, sizeof(short)*total);
  }

  delete list;

  return 0;
}

答案 1 :(得分:1)

你有严重的问题。

对于初学者,您的函数在使用时只有一个输出参数:vCnt。 vList只用作局部变量。

realloc被调用了一些我们不知道的index,不太可能是好的。它必须是从malloc()或realloc()获得的东西。

退出getTrimmedList后,vList中分配的内存就会泄露。

在调用函数的地方,您将本地lstArr数组作为第一个参数传递,该参数不用于任何内容。然后将原始的,未更改的数组打印到cnt中的边界,同时它仍然具有0大小 - 行为未定义。

即使您设法通过ref传递该数组,也无法将其重新分配给其他值--C风格的数组不能这样做。

您最好使用std :: vector,您可以通过引用实际传递并填充被调用的函数。消除冗余大小,重要的是消除内存处理。

答案 2 :(得分:0)

您应该使用std :: vector而不是原始c样式数组,并使用“&amp;”传递引用而不是“*”在这里。现在,您没有正确设置out参数(如果您想要向调用者返回一个新数组,则指向数组的指针看起来像“short ** arr_ptr”而不是“short * arr_ptr” - 此API是然而,正如你所发现的那样,非常容易出错。)

因此,您的getTrimmedList函数应具有此签名:

ErrCode getTrimmedList(std::vector<short> &lst);

现在你不再需要你的“计数”参数--C ++的标准容器都有查询其内容大小的方法。

C ++ 11还让你对int的空间要求更加具体,所以如果你正在寻找一个16位的“short”,你可能想要int16_t。

ErrCode getTrimmedList(std::vector<int16_t> &lst);

避免要求调用者创建“out”数组也是合理的,因为我们在这里使用更智能的容器:

std::vector<int16_t> getTrimmedList(); // not a reference in the return here

在这种风格中,我们可能会使用异常而不是返回代码来管理错误,但是,关于您的界面的其他内容也很可能会发生变化。