Конструктор, который динамически распределяет массив - PullRequest
1 голос
/ 28 октября 2011

У меня проблемы с пониманием конструкторов и, в частности, с тем, как вы можете динамически размещать массив в одном. Может ли кто-нибудь привести пример класса, который имеет массив чисел с плавающей запятой, и конструкторы принимают целочисленный аргумент и динамически распределяют массив для хранения такого количества чисел.

И как другие функции-члены будут обращаться к этому массиву.

Спасибо за помощь и любые другие полезные идеи очень ценны.

РЕДАКТИРОВАТЬ: Я еще не выучил std: vector, есть ли еще более простой способ?

Ответы [ 3 ]

3 голосов
/ 28 октября 2011

Это более или менее то, что делает std::vector, хотя он реализован с гораздо большей универсальностью, поэтому новичку немного сложно прочитать исходную информацию о любой реализации библиотеки (особенно с учетом обычно кошмарных соглашений об именах). используется в стандартном коде библиотеки).

Вот первый динамический массив ребенка:

class MyArray
{
  float * buf;
  std::size_t size;

public:
  explicit MyArray(std::size_t s) : buf(new float[s]), size(s) { }
  ~MyArray() { delete[] buf; }

  // Copying and reassigning is tricky! We disallow it for now.
  MyArray(MyArray const &) = delete;
  MyArray & operator=(MyArray const &) = delete;

  std::size_t size() const { return size; }
  float & operator[](std::size_t i) { return buf[i]; }
  float const & operator[](std::size_t i)  const { return buf[i]; }
};

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

Использование:

MyArray a(20);
a[4] = 6.3;

Более продвинутая версия будет включать функцию resize(); для этого вам нужно выделить и скопировать (скажем):

void resize(std::size_t n)
{
  float * tmp = new float[n];
  std::copy(buf, buf + std::min(size, n), tmp); // I assume this doesn't throw

  delete[] buf;

  buf = tmp;
  size = n;
}

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

1 голос
/ 28 октября 2011
struct Array_holder
{
    float* arr;

    Array_holder(size_t size):
    arr(new float[size])
    {}

    ~Array_holder()
    { delete[] arr; }

    float get(size_t i) const
    { return arr[i]; }
};

при написании этого довольно простого кода я сделал 2 грубых ошибки:

1) я забыл освободить память 2) я не реализовал конструктор копирования и оператор присваивания, которые в соответствии с правилом 3 требуютсяесли в классе есть деструктор.

Это хороший пример того, почему работа с динамической памятью сложна и опасна.Сравните со следующим примером:

#include <vector>

struct Array_holder
{
    std::vector<float> arr;

    Array_holder(size_t size):
    arr(size)
    {}

    float get(size_t i) const
    { return arr.at(i); }
};

Этот пример короче, проще, удобочитаемее, менее подвержен ошибкам и более надежен в использовании.

0 голосов
/ 28 октября 2011

Во-первых, поскольку вы используете C ++, вы должны просто использовать std::vector.

Второй:

class DynamicArray {
    float* array;
public:
    DynamicArray( int size ) { array = new float[ size ]; }
    ~DynamicArray( void ) { delete[] array; }
    float* get( void ) const { return array; }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...