Search code examples
c++arraysinitializationstdunique-ptr

Initialize std::unique_ptr as a raw array pointer is initialized


I currently have a small OpenGL project wherein I create an array on the heap with,

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 
};

I am anticipating expanding this to many hundreds or a thousand values. Thus, I would like to use a std::unique_ptr. I have looked at the documentation and it does not seem that initializing a std::unique_ptr like a raw array pointer is possible. Nonetheless, I have tried writing something like this,

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 
};

which does not compile.

Is there away to initialize a unique_ptr array as with a raw pointer array?

I have thought about using a std::vector and then "capturing" that with a unique_ptr, though I have not tried that yet.


Solution

  • Unless very specific reason, you should aim to use std::vector. This is the standard type for dynamically allocated arrays. my_vector.data() returns a pointer to the data so it's compatible with C apis such as 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 
    };
    

    If you want vector (if you need resizing and such), simply use std::vector<float> as the type instead of std::array<float, 48>


    Now if you want to fix your syntax but still use dynamic memory and pointers (I would advise against, even more because it's for OpenGL vertices and you know the size in advance) simply replace the type, construct it with the new array inside:

    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 
    });
    

    The std::unique_ptr type has a constructor that takes a pointer to the type T. The constructor is explicit only, so only direct initialization must be used.

    Here's a live example with all constructor type.