【问题标题】:c++ Array passing dilemmac++ 数组传递困境
【发布时间】:2010-04-21 10:01:41
【问题描述】:

我正在编写一个函数,它接受一个字符串、字符串指针和一个 int。 该函数根据一组规则拆分字符串并将每个标记放入一个数组中。我需要使用 int 变量中的元素数等从函数中返回数组。我对如何返回数组感到困惑,因为我不能使用 auto 否则它会被破坏,我不愿意使用 new 作为我觉得这是不完整的。

我对如何解决这个问题有其他想法,但想先看看其他人如何解决这个问题。我也可能是错的,有可能从数组中传递一个 auto 。我也不能使用向量,所以有一个复制构造函数。

不能使用矢量,因为这是对我提出的挑战,我被要求不要使用模板。

【问题讨论】:

  • 为什么你认为你不能使用向量?
  • 出于好奇,你为什么不能使用vector
  • 因为我选择不使用vector。
  • 好吧,我选择不回答你的问题。并对其投反对票。
  • 您不认为仅仅因为不使用标准库向量而对某人downvote 有点苛刻吗?赞成反对。

标签: c++ arrays function


【解决方案1】:

考虑到这些限制,这更像是一个 C 而非 C++ 问题。

常见的返回数组的C模式其实就是让调用者传入一个数组来填充。这让调用者决定分配(并因此解除分配)。

你的函数原型应该是这样的

int Function(string str1, string_ptr str2, int n, int* pOutArray, int cOutArray);

其中函数返回写入 pOutArray 的元素数。

在您处理 pOutArray 为 NULL 的实现中,在这种情况下您只需计算元素的数量并返回它。这使您可以根据需要以多种方式之一调用该函数:-

int out[5]={0};
int cFilled = Function(s1,s2,x,out,_countof(out));
// Further code can use up to 5<cFilled elements from the array.

或者,

int cElt = Function(s1,s2,x,NULL,0);
int* pOut = malloc(sizeof(int)*cElt);
Function(s1,s2,x,pOut,cElt);
// pOut now contains exactly the number of elements extracted.
free(pOut);

【讨论】:

    【解决方案2】:

    自然的选择当然是将结果作为std::vector&lt;std::string&gt; 传递。如果您不想使用这种方法,有两种选择:

    1. 让代码的客户端提供结果的存储,在这种情况下,最好让客户端也传递提供的存储的大小。
    2. new为里面的结果分配空间,我认为这是一个更好、更健壮的选择。当然,您必须确保客户端稍后使用正确版本的 delete 删除内存,或者提供一种特殊机制来释放内存。

    【讨论】:

      【解决方案3】:

      如果您要返回一个固定大小的数组,您可以使用boost::array。但是,如果不想添加 Boost 依赖,简单的解决方案是创建一个固定大小数组的数据结构,如下所示:

      模板 结构数组包装器 { T 数组[大小]; };

      如果大小可以改变,那么使用std::vector 确实最有意义。请记住,返回包装类(如上所示)仍将导致创建副本(尽管由编译器创建)。因此,通过按值传递大结果而不是在堆上构造它并传递指向已分配数据的指针,实际上并没有节省任何成本,因此您的要求没有意义。

      【讨论】:

        【解决方案4】:

        传入 'char &** ' 和 'int &* ' 参数并在那里分配令牌,将释放内存的责任留给调用者。 按照现代标准来说不是很好,但很有效。

        【讨论】:

          【解决方案5】:

          如果您选择不使用管理内存的标准方法(即 std::vector),那么您将不得不做出选择。

          三个基本选项是:

          1. 调用者管理内存。调用者传入一块内存(并且可能是一个指定该数组有多大的 int)。你填充那个数组。函数不需要做内存分配。
          2. 被调用者管理内存。该函数分配一个足够大的块,填充它,然后返回一个指向它的指针。
          3. 协作。调用者传递一个回调函数,被调用者使用该函数分配块。

          选项 (2) 因某人需要释放内存而变得复杂。作为 API 的一部分,您需要指定函数是否稍后(以及何时)以某种方式清除该阻塞,或者调用者是否负责。

          选项 (3) 可能有点矫枉过正——你需要编写一个函数来调用主函数。

          因此,选项 (1) 是您最好的选择(如果您不能使用向量)。这是一个非常标准的模式 - 例如,低级 Windows API 使用该模式。

          基本上,内存管理必须记录为 API 的一部分。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-11-15
            • 1970-01-01
            • 2011-10-11
            • 1970-01-01
            • 2012-10-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多