【问题标题】:How to properly return an array (class member) in C++?如何在 C++ 中正确返回数组(类成员)?
【发布时间】:2012-04-10 11:04:39
【问题描述】:

我对 C++ 很陌生,所以这可能是一个微不足道的问题:

我的班级有一个私有成员变量,它是一个数组。我需要返回该数组,但我不确定如何正确执行。

class X {
    // ...
    private: double m_Array[9];
    public: double* GetArray() const { return m_Array; }
};

这段代码有问题吗?这会返回一个指向类成员的指针,对吧? - 因此,如果我从此类的实例中获取该数组并修改它(从类外部),那么原始类成员数组也会被更改吗?如果是这种情况,我该如何返回数组的副本?

【问题讨论】:

  • 如果数组大小不固定,请考虑std::vector< double >(在您的示例中,它似乎是固定的,所以不用担心)。额外的好处:您可以返回对向量的引用。
  • 通常使用对象封装数据和行为。 X 不能做你想做的事有什么原因吗? Tell, don't ask.

标签: c++


【解决方案1】:

这会返回一个指向类成员的指针,对吧?

几乎 - 它返回一个指向数组第一个元素的指针。

如果我从此类的实例中获取该数组并修改它(从类外部),那么原始类成员数组也会被更改吗?

没错。

如果是这样,我该如何返回数组的副本?

实现这一目标的最简单方法是改用std::arraystd::vector。您应该返回对它的 const 引用 - 然后调用者避免在不需要时复制成本。示例:

class X {
    std::array<double, 9> array;
public:
    std::array<double, 9> const & GetArray() const {return array;}
};

X x;
double d = x.GetArray()[5]; // read-only access, no copy

auto array = x.GetArray();  // get a copy
array[5] = 42;              // modify the copy

或者,如果数组具有固定大小(如您的示例中那样),您可以返回包含在结构中的数组 - 这就是 std::array 的含义。否则,您可以将指针(最好是智能指针,以避免内存泄漏)返回到新分配的数组 - 这或多或少是 std::vector 的内容。

【讨论】:

  • 是的,您必须“克隆”它,或者在数组的情况下,将内容复制到新数组中。
  • +1,但是创建某种“数组视图”而不是返回实现运算符 [] 的结构不是更好吗,因为我认为数组复制会占用大量内存和时间
  • @YetAnotherGeek:问题是问如何返回数组的副本,这样可以在不影响原始的情况下进行修改。你不能不复制它。
  • @Niko:通过const 引用而不是按值返回,允许您读取数组而无需复制它,并且只有在需要修改它时才复制它。
  • @MikeSeymour 在这种情况下,可能。首先,其他人可能会像我一样误读它,并认为您的意思是指向成员的智能指针。其次,通常的智能指针不执行数组删除,这在此处是必要的。 Boost 有一些功能,但我敢打赌,大多数没有阅读您的答案就不会知道该怎么做的人不知道它们,或者使用它们的必要性。 (对于我们这些无法保证完全兼容 C++11 的人来说,用于转移所有权的“标准”智能指针是 auto_ptr,它不适用于数组。)
【解决方案2】:

为了返回一个副本,doublenew 数组需要动态分配,填充 m_Array 的当前值并返回给调用者(具体来说是指向第一个元素的指针)。调用者将负责delete[]ing 返回的数组。就目前而言,调用者不知道返回数组中的元素数量。

由于这是 C++,建议改为 std::vector&lt;double&gt;:这将为您处理复制并为调用者提供有关 doubles 数量的信息。

【讨论】:

    【解决方案3】:

    是的,当你改变数组时,你也会改变类成员。

    我建议您在 c++ 中使用 std::vector 而不是 c 样式的数组。它将使您的生活更轻松,并使代码更易于阅读。如果你仍然有理由坚持使用数组,你需要分配一个新的数组并返回一个指向它的指针。请注意,这将迫使您处理动态内存并注意释放它:

    public:
      double* GetArray() {
        double* res = new double[9];
        for (int i = 0; i < 9; ++i) {
          res[i] = m_Array[i];
        }
        return res;
      }
    

    您还可以使用 memcpy 来复制数组的元素。

    【讨论】:

      猜你喜欢
      • 2014-07-23
      • 2014-11-24
      • 1970-01-01
      • 2015-04-29
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-18
      相关资源
      最近更新 更多