Инициализируйте std :: unique_ptr как инициализированный указатель массива - PullRequest
2 голосов
/ 25 июня 2019

В настоящее время у меня есть небольшой проект OpenGL, в котором я создаю массив в куче с

float* vertices = new float[48] {
     0.5f,  0.5f, 0.5f,  1.0f, 0.0f, 0.0f,  // front top right,    0
     0.5f, -0.5f, 0.5f,  0.0f, 1.0f, 0.0f,  // front bottom right, 1
    -0.5f, -0.5f, 0.5f,  0.0f, 0.0f, 1.0f,  // front bottom left,  2
    -0.5f,  0.5f, 0.5f,  0.4f, 0.8f, 0.2f,  // front top left,     3

     0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 0.0f,  // back top right,     4
     0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,  // back bottom right,  5
    -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,  // back bottom left,   6
    -0.5f,  0.5f, -0.5f, 0.4f, 0.8f, 0.2f   // back top left,      7 
};

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

std::unique_ptr<float[]> vertices(new float[48])  {
    0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,     // front top right,    0
    0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,    // front bottom right, 1
   -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,    // front bottom left,  2
   -0.5f, 0.5f, 0.5f, 0.4f, 0.8f, 0.2f,     // front top left,     3

    0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,    // back top right,     4
    0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,   // back bottom right,  5
   -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,   // back bottom left,   6
   -0.5f, 0.5f, -0.5f, 0.4f, 0.8f, 0.2f     // back top left,      7 
};

, который не компилируется.

Можно ли инициализировать массив unique_ptr как с массивом необработанных указателей?

Я думал об использовании std::vector и затем "захвате" этого с помощью unique_ptr, хотя я еще не пробовал это.

1 Ответ

4 голосов
/ 25 июня 2019

Если нет очень конкретной причины, вы должны стремиться использовать std::vector. Это стандартный тип для динамически размещаемых массивов. my_vector.data() возвращает указатель на данные, чтобы он был совместим с C apis, таким как OpenGL.

// on the heap
std::vector<float> vertices = {
     0.5f,  0.5f, 0.5f,  1.0f, 0.0f, 0.0f,  // front top right,    0
     0.5f, -0.5f, 0.5f,  0.0f, 1.0f, 0.0f,  // front bottom right, 1
    -0.5f, -0.5f, 0.5f,  0.0f, 0.0f, 1.0f,  // front bottom left,  2
    -0.5f,  0.5f, 0.5f,  0.4f, 0.8f, 0.2f,  // front top left,     3

     0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 0.0f,  // back top right,     4
     0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,  // back bottom right,  5
    -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,  // back bottom left,   6
    -0.5f,  0.5f, -0.5f, 0.4f, 0.8f, 0.2f   // back top left,      7 
};

Если вам нужен вектор (если вам нужно изменить размер и тому подобное), просто используйте std::vector<float> в качестве типа вместо std::array<float, 48>


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

std::unique_ptr<float[]> vertices(new float[48] {
     0.5f,  0.5f, 0.5f,  1.0f, 0.0f, 0.0f,  // front top right,    0
     0.5f, -0.5f, 0.5f,  0.0f, 1.0f, 0.0f,  // front bottom right, 1
    -0.5f, -0.5f, 0.5f,  0.0f, 0.0f, 1.0f,  // front bottom left,  2
    -0.5f,  0.5f, 0.5f,  0.4f, 0.8f, 0.2f,  // front top left,     3

     0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 0.0f,  // back top right,     4
     0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,  // back bottom right,  5
    -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,  // back bottom left,   6
    -0.5f,  0.5f, -0.5f, 0.4f, 0.8f, 0.2f   // back top left,      7 
});

Тип std::unique_ptr имеет конструктор, который принимает указатель на тип T. Конструктор только явный, поэтому должна использоваться только прямая инициализация.

Вот живой пример со всеми типами конструктора.

...