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

11

我对C++还不太熟悉,所以这可能是一个基础问题:

我的类有一个私有成员变量是一个数组。我需要返回这个数组,但我不确定如何正确地做到这一点。

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

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


2
如果数组大小不固定,请考虑使用std::vector<double>(在您的示例中似乎是固定的,所以不必担心)。额外的好处是,您可以返回对向量的引用。 - hochl
2
通常,使用对象来封装数据和行为。X不能做你想要的事情吗?告诉别问 - Peter Wood
3个回答

11

这会返回该类成员的指针,对吗?

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

如果我从该类的实例中提取该数组并对其进行修改(在类之外),原始类成员的数组也会发生变化吗?

是的,没错。

如果是这样,那么如何返回数组的副本呢?

最简单的方法是改用 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 的作用。


是的,您需要“克隆”它,或者在数组的情况下,将内容复制到一个新数组中。 - user1086498
@YetAnotherGeek:这个问题要求返回数组的副本,以便可以在不影响原始数组的情况下进行修改。如果不复制它,就无法做到这一点。 - Mike Seymour
谢谢,这正是我在寻找的内容。但是对于你的示例代码,我有一个简短的跟进问题:为什么const&中的“&”是必需的? - Niko
2
@Niko:通过使用const引用返回,而不是返回值,可以让你在不复制数组的情况下读取它,并且只有在需要修改它时才进行复制。 - Mike Seymour
1
在这种情况下,很可能会出现误读,像我一样认为您指的是成员的智能指针。第二,通常的智能指针不执行数组删除,在这里是必要的。Boost有一些可以执行此操作的智能指针,但我愿意打赌,大多数人不知道如何在没有阅读您答案的情况下使用它们,也不知道使用它们的必要性。(对于那些无法保证完全兼容C++11的人来说,用于转移所有权的“标准”智能指针是auto_ptr,但它不能处理数组。) - James Kanze
显示剩余6条评论

2

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

我建议你在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来复制数组的元素。

2
为了返回一个 double 数组的副本,需要动态分配一个 new 数组,并填充当前 m_Array 的值,然后将指针返回给调用者(具体来说是第一个元素的指针)。调用者需要负责 delete[] 返回的数组。目前来看,调用者并不知道返回的数组中有多少个元素。
由于这是 C++,建议改为使用 std::vector<double>:它会自动处理复制,并向调用者提供关于 double 数量的信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接