问题 如何在C ++中正确返回数组(类成员)?


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

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

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

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


12131
2018-04-10 11:04


起源

考虑 std::vector< double > 如果数组大小不固定(在您的示例中它似乎是固定的,所以不用担心)。增加的好处:您可以返回对向量的引用。 - hochl
通常使用对象封装数据和行为。有原因吗? X 不能做你想要的? 告诉,不要问。 - Peter Wood


答案:


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

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

如果我从这个类的实例中获取该数组并修改它(从类外部),原始的类成员数组也将被更改?

那是对的。

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

实现这一目标的最简单方法是使用 std::array 要么 std::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 是。


11
2018-04-10 11:08



是的,你必须'克隆'它,或者在数组的情况下,将内容复制到一个新的数组中。
+1,但不是更好的创建一些'数组视图'而不是返回一个实现operator []的结构,因为我认为数组复制将使用大量的内存和时间 - Yet Another Geek
@YetAnotherGeek:问题是如何返回数组的副本,因此可以修改它而不影响原始数据。没有复制它就不能这样做。 - Mike Seymour
@Niko:回归 const 引用而不是值,允许您读取数组而无需复制它,并且只有在需要修改它时才复制它。 - Mike Seymour
@MikeSeymour在这种情况下,可能。首先,其他人可能会像我一样误读它,并认为你的意思是指向会员的智能指针。第二,通常的智能指针不进行数组删除,这在这里是必要的。 Boost有一些可以这样做,但我愿意打赌,大多数不知道如何做而没有阅读你的答案的人都不知道他们,或者使用它们的必要性。 (用于转移所有权的“标准”智能指针,对于我们这些无法保证完全符合C ++ 11的人来说,是 auto_ptr,这不适用于数组。) - James Kanze


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

因为这是C ++,建议改为a std::vector<double> 相反:这将为您处理复制并为呼叫者提供有关数量的信息 double秒。


2
2018-04-10 11:09





是的,当您更改阵列时,您还将更改类成员。

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

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

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


2
2018-04-10 11:10