【问题标题】:Array as out parameter in c++数组作为c ++中的输出参数
【发布时间】:2013-06-24 08:58:24
【问题描述】:

我创建了一个返回错误代码 (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() 返回 ith FooBar 对象,类型为 FOO_TYPE_1
  • bar.isDeleted 是一个标志,表明 bar 是否被视为“已删除”

我的错误是什么?

编辑:

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

编辑 2

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

【问题讨论】:

  • 那不是C++代码,那是C代码。对于 C++,您应该改用 std::vector

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


【解决方案1】:

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

“索引”在哪里定义: 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;
}

【讨论】:

  • 相信作者的意图是把vList作为out参数返回。不知道 index 来自哪里,但基于这里的其他 Foo* 接口,我认为有些魔法被遗漏了。
  • 我只是想澄清一下,因为“魔法”可能要为他糟糕的一天负责。 ;)
  • @ReignBough 检查这个例子,我相信它就是你要找的。​​span>
  • 我仍然认为,鉴于这是标记为 C++,您应该遵循更规范的 C++ 样式。您的代码也将更加健壮和可读。
【解决方案2】:

你有严重的问题。

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

realloc 是用一些 index 调用的,我们对此一无所知,可能不太好。它一定是从 malloc() 或 realloc() 得到的。

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

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

即使您设法通过 ref 传递该数组,也无法将其重新分配给不同的值——C 样式的数组无法做到这一点。

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

【讨论】:

    【解决方案3】:

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

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

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

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

    C++11 还允许您更具体地了解整数的空间要求,因此如果您正在寻找 16 位“短”,您可能需要 int16_t。

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2017-02-18
      • 1970-01-01
      • 1970-01-01
      • 2021-10-01
      • 1970-01-01
      • 2013-11-09
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      相关资源
      最近更新 更多