Hi all,

I am attempting to assign values to a multidimensional array but am having difficulty.

This isn't the exact code that I'm using, but the idea is this:

for(int T=0; T<5; T++)
    {
        array[T][3][4] ={{4,2,6,4},{5,2,5,3},{6,3,1,5}}
    }

For all T from T=0 to T=4, assign the same values shown above. That is:

Array[0][3][4] = Array[1][3][4] = ... = Array[4][3][4].

How can I go about doing this?

Thank you so much.

Dani AI

Generated

Short summary and a few gotchas: the goal was to copy the same 3×4 block into each slice of a 3D array. Make sure the slice shape and the temporary block match (for a slice that is 3 rows × 4 columns declare the array as int arr[5][3][4]). ’s idea (create a single initialized block and copy it into each arr[t]) is the right pattern for plain integers; confirmed it fixed the immediate problem. ’s warning is also important: raw memcpy or placement tricks are inappropriate for non‑POD types.

A compact, safe approach that works for ordinary element types is to use std::copy and a compile‑time size check:

#include <algorithm>

int arr[5][3][4];
int block[3][4] = {
  {4,2,6,4},
  {5,2,5,3},
  {6,3,1,5}
};

static_assert(sizeof(block) == sizeof(arr[0]), "pattern and slice must have same size");

for (int t = 0; t < 5; ++t)
    std::copy(&block[0][0], &block[0][0] + (3*4), &arr[t][0][0]);

When to choose what:

  • For built‑ins (ints) the above is simple and portable.
  • For non‑POD or user types, prefer element‑wise assignment (nested loops, std::copy with matching typed elements, or container assignment); avoid memcpy or placement‑new until you understand object lifetime rules (see and for advanced patterns).
  • If you use nested std::vector rows, you cannot treat the data as one contiguous block — copy per row or use a contiguous container (single vector or std::array wrappers).

Quick troubleshooting: double‑check your dimension order, use static_assert or sizeof to verify slice sizes, and test by printing a single slice before doing the full loop.

Recommended Answers

All 8 Replies

How about making a temporary 3 x 4 array, initialize it as you have done, then in your for loop, do a memcpy of the 3 x 4 array to the address of element array[T][0][0]?

const int temp[3][4] = {{4,2,6,4},{5,2,5,3},{6,3,1,5}};
int array[5][4][3];

// Replace line 3 in your original code snippet with this...
memcpy(&array[T][0][0], &temp[0][0], sizeof(temp));

That's great! It solved my problem. Thanks!

How about making a temporary 3 x 4 array, initialize it as you have done, then in your for loop, do a memcpy of the 3 x 4 array to the address of element array[T][0][0]?

That's fine for arrays of built-in types, but if you're working with a non-POD type then memcpy() is an exceptionally bad idea because it invokes undefined behavior.

That's a good point deceptikon, do you have a solution? I do, of course, but it gets tricky.

Of course, you can't use memcpy and expect well-defined behaviour for any non-POD type. You can manage to force an element-wise copy-construction into the destination array by the following trick:

template <typename T>
void initializeArray(T (&arr)[5][4][3]) {      
  for(int i = 0; i < 5; ++i) {
    // create a local aggregate struct that you use to represent sub-arrays:
    struct local_sub_array {
      T data[4][3];
    };
    // create your static const sub-array:
    static const local_sub_array rhs = {{{4,2,6},{4,5,2},{5,3,6},{3,1,5}}};
    // use the placement-new and the copy-constructor of the local class to force
    //  the use of element-wise copy-constructors if they are needed (non-POD):
    new( (local_fixed_array*) &arr[i] ) local_sub_array(rhs);
  };
};

The placement-new operator is very often used as a "constructor-calling memcpy replacement", but that is usually a bad idea. There is a big flaw in the above solution because the array is already constructed when you attempt to overwrite it with copy-constructed elements. You can't overwrite a constructed object, you need to destroy it first. In other words, you'll need to add this part:

template <typename T>
void initializeArray(T (&arr)[5][4][3]) {

  for(int i = 0; i < 5; ++i)
    for(int j = 0; j < 4; ++j)
      for(int k = 0; k < 3; ++k)
        arr[i][j][k].~T();       // call destructor on each element.
                                 // NOTE: Don't attempt to reproduce this at home.
                                 // This was done by a trained professional (me!).

  for(int i = 0; i < 5; ++i) {
    // create a local aggregate struct that you use to represent sub-arrays:
    struct local_sub_array {
      T data[4][3];
    };
    // create your static const sub-array:
    static const local_sub_array rhs = {{{4,2,6},{4,5,2},{5,3,6},{3,1,5}}};
    // use the placement-new and the copy-constructor of the local class to force
    //  the use of element-wise copy-constructors if they are needed (non-POD):
    new( (local_fixed_array*) &arr[i] ) local_sub_array(rhs);
  };
};

But, the problem with the above is that if you are going to have to write out this triple nested loop, you might as well just do this instead:

template <typename T>
void initializeArray(T (&arr)[5][4][3]) {
  static const rhs[4][3] = {{4,2,6},{4,5,2},{5,3,6},{3,1,5}};
  for(int i = 0; i < 5; ++i)
    for(int j = 0; j < 4; ++j)
      for(int k = 0; k < 3; ++k)
        arr[i][j][k] = rhs[j][k];
};

Now, the problem with the above is that it can be inefficient if your type is a POD type, because in that case, the compiler can figure out that a batch memcpy (under-the-hood) is going to be more efficient than individual assignments. So, what you really need is a batch copy-assignment. So, we can do as in the first example, and replace the batch copy-construction with a batch copy-assignment, as so:

template <typename T>
void initializeArray(T (&arr)[5][4][3]) {      
  for(int i = 0; i < 5; ++i) {
    // create a local aggregate struct that you use to represent sub-arrays:
    struct local_sub_array {
      T data[4][3];
    };
    // create your static const sub-array:
    static const local_sub_array rhs = {{{4,2,6},{4,5,2},{5,3,6},{3,1,5}}};
    // use the copy-assignment of the local class to force
    //  the use of element-wise copy-assignments if they are needed (non-POD):
    *( (local_fixed_array*) &arr[i] ) = rhs;
  };
};

Now, we have a reasonable solution which is relatively short and simple (three lines in the loop), is correct and well-behaved for non-POD types, and is as efficient as can be in any situation (POD or not).

Furthermore, if you have a C++11 capable compiler, then you have access to a nice class called std::array which also happens to be an aggregate class (like that local class I created for the purpose of casting, meaning that the standard guarantees binary compatibility with a C-style static array). In other words, you can simplify all of the above to a simple one-liner:

template <typename T>
void initializeArray(T (&arr)[5][4][3]) {
  typedef std::array<std::array<T,3>,4> sub_array;
  for(int i = 0; i < 5; ++i)
    *( (sub_array*) &arr[i] ) = sub_array{{{4,2,6},{4,5,2},{5,3,6},{3,1,5}}};
};

Or, even this:

template <typename T>
void initializeArray(T (&arr)[5][4][3]) {
  typedef std::array<std::array<T,3>,4> sub_array;
  ((std::array<sub_array,5>*)&arr)->fill( sub_array{{{4,2,6},{4,5,2},{5,3,6},{3,1,5}}} );
};

Simple is it not? I love C++11!

That's a good point deceptikon, do you have a solution?

The OP's exact needs aren't clear, so I'm not confident in offering a concrete solution, but in general for something like this I'd favor wrapping the tediousness inside an object. Something like a matrix class or nested vectors.

Is that vague enough? :D

Yes, definitely, for ease of use in the future, the OP should not rely on a static array, but create, instead, a vector/matrix/tensor class for his particular purpose. Or, at the very least, rely on a more practical static-size array representation, like std::array, if available to him.

The OP's question referred to a three-dimensional array of integers, which would not be a non-POD type. The non-POD discussion is interesting, but does it apply here? memcpy will do the job just fine, and safely. Are you guys just pointing out the need to be careful and that it won't work in some OTHER scenario or do you disagree with its use in this particular case?

Well, strictly speaking, from the OP's question, there is not implication that the value-type of the array is an integer, only that it is constructible or assignable with an integer value. So, there is a slight chance that the non-POD case is relevant. Also, to me, it seemed like the relevant part of the question was on how to assign an entire sub-array (or sub-array-of-array) without having to do two nested loops to assign each individual element, so I thought it would be salient to include a general solution to that problem.

And, of course, for a POD type (like int) the memcpy solution is totally fine, given that you are aware that it does not apply to non-POD types, a fact that is relevant to point out. When applying such a method, there is a fine line between doing so because you know that it is OK in this particular case, and doing so because you think it is the general way to do it. I, like deceptikon, don't want the OP to be mislead into the latter category.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.