0

I want to create a constant (preferably static but not necessary) member variable in my class.
I want it to be a 3-dimensional array with each length size 2.
The purpose: store some data that is time consuming to recreate on each change, for combinations of 3 types of boolean choices, without having to do complicated testing on each change.

What I don't know how to do: how to initialize the 3D array.

This is what I am trying (based on cplusplus.com/forum/Multi-Dimensional Arrays):

class MyClass {
public: ...
    ~MyClass();   // will I need to destroy m_previewIcons to prevent memory leak ?
private: ...
    static const QIcon m_previewIcons[2][2][2];   // the array I need
    static QIcon*** initializePreviewIcons();     // what type of return ?
};

const QIcon MyClass::m_previewIcons[2][2][2] = MyClass::initializePreviewIcons();

QIcon ***MyClass ::initializePreviewIcons()
{
    QIcon ***iconArray = 0;

    // Allocate memory
    iconArray = new QIcon**[2];
    for (int i = 0; i < 2; ++i)
    {
        iconArray[i] = new QIcon*[2];
        for (int j = 0; j < 2; ++j)
            iconArray[i][j] = new QIcon[2];
            // is this even right ? it seems to me I miss out on a dimension ?
    }

    // Assign values
    iconArray[0][0][0] = QIcon(":/image1.png"); 
    iconArray[0][0][1] = QIcon(":/image2.png"); ...
    iconArray[1][1][1] = QIcon(":/image8.png");

    return iconArray;
}

As far as I got...

error: conversion from 'QIcon***' to non-scalar type 'QIcon' requested

How can I get this initialization to work ?

Note - QIcon is a built-in class in Qt, which is what I use (any class would be the same).
No C++ 11 though.

I could have used vectors I suppose but I wanted less overhead.

Edit: I have just thought of an alternate way to do it... give up on the 3D array, use simple 1D array and build an int for index using the booleans bit shifted. may be more effective.
But I would still want to know how to initialize a 3D array.

8
  • 1
    You can use std::array instead. It has no overhead compared to C arrays and it has value semantics, so assignment will preform a copy. Commented Mar 9, 2017 at 15:54
  • Unrelated, but more than 2 * make me dizzy (QIcon***) Commented Mar 9, 2017 at 15:54
  • @FrançoisAndrieux How will I be able to simplify the assignment in that case ? Commented Mar 9, 2017 at 15:56
  • Too much stars in this code. Linearize iconArray as std::array<QIcon, 8> and define Icon& icaonAt(unsigned x, unsigned y, unsigned z) { return iconArray.at(x*4+y*2+z); }. Commented Mar 9, 2017 at 15:56
  • 2
    @YSC Also worth mentioning that linearization is cache-local friendly, i.e. everything is stored contiguously and in performance critical code this will make a big difference. With multiple indirections there is no guarantee that the memory will be contiguous. Commented Mar 9, 2017 at 16:10

2 Answers 2

2

You're creating a a static array, and then trying to allocate its memory dynamically, which isn't necessary - the memory is already there by virtue of your declaration static const QIcon m_previewIcons[2][2][2];

You should initialize your 3d array using list initialization, a la this answer.

Heres an example with a non-POD type, std::string:

#include <string>

class MyClass {
public:
     static const std::string m_previewIcons[2][2][2];
};

const std::string MyClass::m_previewIcons[2][2][2] = { 
                               { {":/image1.png",":/image2.png"},
                                 {":/image3.png",":/image4.png"} }, 
                               { {":/image5.png",":/image6.png"},
                                 {":/image7.png",":/image8.png"} } 
                            };
int main()
{
    MyClass mc;
    printf("%s\n", mc.m_previewIcons[0][0][0].c_str());
}
Sign up to request clarification or add additional context in comments.

4 Comments

Would be even better to provide a snippet.
The reason I tried the "dynamic allocation" is because I could not make a return type for my function to use anything similar to the static type. Thanks for reply, I have seen examples like this but for very simple types - int or char. I must make the elements a bit more complicated.
@FrançoisAndrieux IT is blocking it... it may take a while for them to respond and unblock it, I will take a look if they do, thanks
I added a simple compilable example with a non-POD type, you can do the same thing with your QIcon class
1

The problem is that C++ provides no class initialization: only static initializers or instance constructor.

But here, it is easy, because the construction of the elements of the array is straightforward, so you could use:

class MyClass {
public: ...
    ~MyClass();   // will I need to destroy m_previewIcons to prevent memory leak ?
private: ...
    static const QIcon m_previewIcons[2][2][2];   // the array I need
};

const QIcon MyClass::m_previewIcons[2][2][2] = {
    QIcon(":/image1.png"),
    QIcon(":/image2.png"),
    ...,
    QIcon(":/image8.png") };

As m_previewIcons has static linkage, its duration is the whole program so you have neither to provide storage for it nor to release it. Said differently, do not destroy it from the destructor.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.