Могу ли я получить память в куче для массива в списке инициализации из ранее упомянутых переменных экземпляра? - PullRequest
0 голосов
/ 01 апреля 2020

Я пытаюсь выделить память в куче для массива при создании объекта в моем конструкторе. Размер массива определяется предварительно инициализированными переменными экземпляра. Вот мой код для ясности.

struct PNG {

    PNG() = delete;
    PNG(unsigned width, unsigned height):
        d_width(width),
        d_height(height),
        d_imageData(new unsigned int [d_width * d_height])
    {
    };

    PNG(PNG const &);

    PNG & operator = (PNG & other);

    friend std::ostream & operator << (std::ostream & os, PNG & png);

    unsigned d_width;
    unsigned d_height;
    unsigned d_imageData; // unsigned d_imageData []; has the same issue
};

Этот код выдает мне ошибку:

error: cannot initialize a member subobject of type 'unsigned int' with an rvalue of
      type 'unsigned int *'
        d_imageData(new unsigned int [d_width * d_height])

Меня смущают две вещи:

  1. , как я вижу, массив будет будет запрашивать память и будет контейнером, следовательно, lvalue, а не rvalue, который не будет иметь хранилища.
  2. Доступны ли переменные d_width, d_height после их собственного упоминания в списке инициализации?

Я видел, как это делается таким образом, но хотел попробовать список инициализации. Теперь я изучаю что-то новое, играя с кодом. Это единственный способ, который возможен?

PNG(unsigned int width, unsigned int height) {
    width_ = width;
    height_ = height;
    imageData_ = new HSLAPixel[width * height];
  }

Этот вопрос подходит близко, но он использует std::initializer_list, который я не пытаюсь использовать, и мне не понадобятся шаблоны, как предложено в принятом ответе. Что еще более важно, значения массива будут заполнены позже, а не при построении объекта.

1 Ответ

1 голос
/ 01 апреля 2020

Ваш конструктор в порядке. Но поскольку вы выделяете память для d_imageData, используя new[], вам нужно объявить d_imageData как тип указателя, а не целочисленный тип, например:

unsigned int *d_imageData; // <-- notice the *

(и не забудьте включите деструктор, который вызывает delete[] d_imageData; - см. Правило 3/5/0 ).

И да, вы можете использовать d_width и d_height при вызове new[] в списке инициализатора члена вашего конструктора, так как они объявлены до d_imageData в объявлении PNG и, следовательно, инициализируются до d_imageData.

...