Как правильно вернуть массив (член класса) в С++?

Я новичок в С++, поэтому это может быть тривиальный вопрос:

В моем классе есть частная переменная-член, которая является массивом. Мне нужно вернуть этот массив, но я не уверен, как это сделать.

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

Есть ли проблемы с этим кодом? Это возвращает указатель на член класса, правильно? - так, если я получаю этот массив из экземпляра этого класса и изменяю его (вне класса), будет также изменен исходный массив элементов класса? Если это так, как мне вернуть копию массива?

Ответ 1

Это возвращает указатель на член класса, правильно?

Почти - он возвращает указатель на первый элемент массива.

если я получаю этот массив из экземпляра этого класса и изменяю его (вне класса), будет также изменен исходный массив элементов класса?

Это правильно.

Если это так, как мне вернуть копию массива?

Самый простой способ добиться этого - использовать 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.

Ответ 2

Чтобы вернуть копию, массив new double должен был бы динамически распределяться, заполнять текущие значения m_Array и возвращаться вызывающему (указатель на конкретный первый элемент). Вызывающий абонент будет отвечать за delete[] за возвращаемый массив. Как бы то ни было, вызывающий объект не знает количества элементов в возвращаемом массиве.

Так как это С++, предложите вместо этого изменить std::vector<double>: это обработает для вас копирование и предоставит вызывающей стороне информацию о количестве double s.

Ответ 3

Да, при изменении массива вы также измените член класса.

Я бы рекомендовал использовать std::vector вместо c-style array в С++. Это упростит вашу жизнь и сделает код более удобным для чтения. Если по-прежнему есть причина, по которой вы настаиваете на использовании массива, вам нужно выделить новый массив и вернуть указатель на него. Обратите внимание, что это заставит вас работать с динамической памятью и позаботиться о ее освобождении:

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

Вы также можете использовать memcpy для копирования элементов массива.