How to aggregate-initialize STL container in expression with new operator? - c++

I'm trying to do something like:
using std::array;
array< array<int, 3>*, 10> arrsPtrs;
void f()
{
arrsPtrs[0] = new array<int, 3> {1, 2, 3}; //bad!
arrsPtrs[0] = new array<int, 3> {{1, 2, 3}}; //bad!
arrsPtrs[0] = new array<int, 3> ( {1, 2, 3} ); //bad!
arrsPtrs[0] = new array<int, 3> ( {{1, 2, 3}} ); //bad!
}
Is it possible to aggregate-initialize STL container in such expression?
PS: may be it's important - I have VS2010.

You want arrayPtrs[0] = new array<int, 3> {{1,2,3}}.
That having been said, why are you doing this? Having an array of pointers to dynamically allocated arrays is almost certainly the wrong way of going about whatever you are trying to do.
Edit: Effectively, every time you new something in C++, you need a corresponding delete. Unlike languages like Java or C# (that are garbage collected), you should rarely use a raw new in modern C++, as it can very easily lead to memory leaks.
Basically, instead of:
array<array<int, 3>*, 10> arrsPtrs;
You instead would want to use:
array<array<int, 3>, 10> arrsPtrs;
If you want to pass this to a function, you can simply pass it by (const) reference:
void some_function(const array<array<int, 3>, 10>& arr)
{
....
}

Related

List initialization for array<array<int, M>, N>

When initializing a 2D array we can do
int data[2][2] = {{1, 2}, {3, 4}}; // OK
we can also use
int data[2][2] = {1, 2, 3, 4}; // OK
which makes sense since a 2D array still is a continues chunk of memory.
When using the array class instead of the base type, this works
array<array<int, 2>, 2> data = {1, 2, 3, 4}; // OK
Which again makes sense, since array class doesn't have any extra data and ends up as a continues chunk of memory as well.
But the 2D list does not work:
array<array<int, 2>, 2> data = {{1, 2}, {3, 4}}; // Error
I can also initialize this
vector<array<int, 2>> data = {{1, 2}, {3, 4}}; // OK
But couldn't find anyway to initialize:
array<vector<int>, 2> = ????
My question is:
Is there a fundamental design reason for this (My guess is something related to stuff happening at compile-time vs run-time)? Or is this just an implementation decision for the compiler I am using (GCC)?
std::array doesn't have any user-defined constructor (like std::vector), it just contains a underlying array, when performing aggregate initialization you need one more braces for it.
array<array<int, 2>, 2> data = {{{{1, 2}}, {{3, 4}}}};
// ^ ^ <- for array<array<int, 2>, 2>
// ^ ^ <- for the underlying array
// ^ ^ <- for the 1st array<int, 2>
// ^ ^ <- for its underlying array
// ^ ^ <- for the 2nd array<int, 2>
// ^ ^ <- for its underlying array
We can omit braces as
array<int, 2> data = {1, 2};
array<array<int, 2>, 2> data = {1, 2, 3, 4};
because of brace elision:
The braces around the nested initializer lists may be elided (omitted), in which case as many initializer clauses as necessary are used to initialize every member or element of the corresponding subaggregate, and the subsequent initializer clauses are used to initialize the following members of the object.
That means the above code code be written as
array<array<int, 2>, 2> data = {{{1, 2}, {3, 4}}};
And array<array<int, 2>, 2> data = {{1, 2}, {3, 4}}; fails because it's interpreted as:
array<array<int, 2>, 2> data = {{1, 2}, {3, 4}};
// ^ ^ <- for array<array<int, 2>, 2>
// ^ ^ <- for the underlying array
// ^ ^ <- excess elements; std::array has only one underlying array

Initialise a dynamically allocated array [duplicate]

In C++, I can statically initialize an array, e.g.:
int a[] = { 1, 2, 3 };
Is there an easy way to initialize a dynamically-allocated array to a set of immediate values?
int *p = new int[3];
p = { 1, 2, 3 }; // syntax error
...or do I absolutely have to copy these values manually?
You can in C++0x:
int* p = new int[3] { 1, 2, 3 };
...
delete[] p;
But I like vectors better:
std::vector<int> v { 1, 2, 3 };
If you don't have a C++0x compiler, boost can help you:
#include <boost/assign/list_of.hpp>
using boost::assign::list_of;
vector<int> v = list_of(1)(2)(3);
You have to assign each element of the dynamic array explicitly (e.g. in a for or while loop)
However the syntax int *p = new int [3](); does initialize all elements to 0 (value initialization $8.5/5)
To avoid endless push_backs, I usually initialize a tr1::array and create a std::vector (or any other container std container) out of the result;
const std::tr1::array<T, 6> values = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(values.begin(), values.end());
The only annoyance here is that you have to provide the number of values explicitly.
This can of course be done without using a tr1::array aswell;
const T values[] = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(&values[0], &values[sizeof(values)/sizeof(values[0])]);
Althrough you dont have to provide the number of elements explicitly, I prefer the first version.
No, you cannot initialize a dynamically created array in the same way.
Most of the time you'll find yourself using dynamic allocation in situations where static initialization doesn't really make sense anyway. Such as when you have arrays containing thousands of items. So this isn't usually a big deal.
Using helper variable:
const int p_data[] = {1, 2, 3};
int* p = (int*)memcpy(new int[3], p_data, sizeof(p_data));
or, one line
int p_data[] = {1, 2, 3}, *p = (int*)memcpy(new int[3], p_data, sizeof(p_data));
Never heard of such thing possible, that would be nice to have.
Keep in mind that by initializing the array in the code that way
int a[] = { 1, 2, 3 };
..... only gains you easier code writing and NOT performance.
After all, the CPU will do the work of assigning values to the array, either way you do it.

Set array1 = array2 in C++

I have one initialized array arr1 and one declared array arr2. How can I simply set arr2 = arr1?
void setup() {
int arr1[5][2]= { {1,1},
{1,2}};
int arr2[5][2];
arr2 = arr1; // Throws error "invalid array assignment"
}
Is it possible to do that in C++? And if so, how? I'd like to prevent using loops for this.
Arrays can't be assigned, but they can be copied (using e.g. std::copy or std::memcpy).
A possible better solution is to use std::array instead, as then you can use plain and simple assignment:
std::array<std::array<int, 2>, 5> arr1 = {{
{ 1, 1 },
{ 1, 2 }
}};
std::array<std::array<int, 2>, 5> arr2;
arr2 = arr1;
You can’t assign C arrays in this way, but you can assign std::arrays and std::vectors:
auto a1 = std::vector<std::vector<int>>{{1, 1}, {1, 2}};
auto a2 = a1;
(std::arrays work the same way but are more verbose, since you need to specify the number of dimensions as template arguments.)
This example performs copy construction rather than assignment, which is what you’ll want to use 99% of the time. Assignment also works, the same way.
It is worth noting that this is not a multi-dimensional array — it’s a nested array. C++ has no native type for multi-dimensional arrays, but various libraries (mostly for numerical computation) provide them, for instance Eigen and xtensor. These may seem superficially similar to nested arrays, but both their API and their implementation differ in crucial ways. Notably, they are laid out contiguously in memory, which nested vectors aren’t (though nested std::arrays are).
Use std::array:
void setup() {
std::array<std::array<int, 2>, 2> arr1= { {1,1},
{1,2}};
std::array<std::array<int, 2>, 2> arr2;
arr2 = arr1;
}
The easiest solution is to use C++, not C.
std::array<std::array<int,5>,5> arr1 =
{ {1,1},
{1,2} };
auto arr2 = arr1;
Use std::array instead of raw C arrays: it's a POD and can be copied (copy assignment; overwrites every element of the array with the corresponding element of another array) in a natural manner:
#include <array>
#include <iostream>
int main() {
using ArrayType = std::array<std::array<int, 2>, 3>;
ArrayType arr{{
{1, 2},
{3, 4},
{5, 6}
}};
ArrayType arr_copy;
// Copy arr into arr_copy.
arr_copy = arr;
// Mutation of original array will not affect the
// elements of the copy.
arr[0][0] = 42;
std::cout << arr_copy[0][0]; // 1 (original value)
return 0;
}

decltype() doesn't work for class template being compiled

I have the following snippet of code having a problem.
I think the compiler can't deduc the type because the type of the elements of values won't b known before compiling. Is that right?
vector values{1, 2, 3, 4, 5, 6};
vector<decltype(values[0])> {values};
ostream_iterator<int> printer{cout," "};
copy(ints.crbegin(),ints.crend(),printer);
The problem here is that values[0] is a int &. See for yourself:
static_assert(std::is_same_v<decltype(values[0]), int &>);
Creating a vector of references is all kinds of wrong. To fix this, just use decltype on the whole vector.
std::vector values{1, 2, 3, 4, 5, 6};
decltype(values) ints(values.cbegin(), values.cend());
For your example, none of this is really necessary because you're just copying a vector. So you can just do this:
std::vector ints = values;
// Or avoid CTAD entirely
auto ints = values;

How to use a 2d array to declare an array_view or array object in c++ AMP

I'm trying to use an array such as int myarray[2][3] to initialize an array_view object. I've tried array_view<int, 2> a(2,3, myarray); However that does not work. I would also like to be able to do the same thing with a vector. Any ideas?
Try array_view<int, 2> a(2, 3, *myarray);
EDIT :
A vector of (fixed-size) vectors can't be used directly to init an array_view object.
However you could do something like that:
vector< vector<int> > my_multi_vector; // Fill my_multi_vector with data
vector<int> my_composed_vector;
for(int i = 0, ie = my_multi_vector.size(); i != ie; ++i)
my_composed_vector.insert(my_composed_vector.end(), my_multi_vector[i].begin(), my_multi_vector[i].end());
array_view<int, 2> a(2, 3, &my_composed_vector.front());
Baltram’s method is correct.
And you can replace
array_view<int, 2> a(2, 3, &my_composed_vector.front());
by
array_view<int, 2> a(2, 3, my_composed_vector);
to make it simpler.
Here is an even more simpler way:
int myarray[2][3];
int *p = &myarray[0][0];
array_view<int, 2> a(2, 3, p);
Thanks,