Set array1 = array2 in C++ - 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;
}

Related

Sorting 2d array using std sort without vector [duplicate]

I cannot seem to sort a 2 dimensional c array with std::sort. I can however sort a one dimensional array. This is in a case where I am being handed a c array in a c++ program and am hoping to sort without copying it over to a std::array. Maybe there is some way to turn it into a std::array without copying it? That sounds doubtful to me as any std::array would then call a destructor on memory that it does not own.
Sorting One dimensional c style array works just fine:
int len = 5;
auto one_dim_less = [](int a, int b){
return a < b;
};
int one_dim[] = {4, 0, 3, 1, 2};
std::sort(one_dim, one_dim + len, one_dim_less);
Attempting to sort two dimensional c style array by second number does not compile:
int len = 5;
auto two_dim_less = [](int a[2], int b[2]){
return a[1] < b[1];
};
int two_dim[][2] = {{1,8}, {2,4}, {3,10}, {4,40}, {5,1}};
std::sort(two_dim, two_dim + len, two_dim_less);
Maybe there is some way to turn it into a std::array without copying
it?
Perhaps not turning into a std::array per se, but an alternative approach might be to cast the 2D C-style arrays into a std::array reference just for the sorting. Doing so in reliance on the standard saying an std::array representation in memory at least begins with its C-style array equivalent. See here under [array.overview§2]:
An array is an aggregate that can be list-initialized with up to N
elements whose types are convertible to T.
In practice, the following usage of reinterpret_cast is most probably safe, but do note that unless there is a special exception for it somewhere in the standard, it would formally be undefined behaviour:
#include <algorithm>
#include <array>
#include <iostream>
int main() {
auto two_dim_less = [](std::array<int, 2>& a, std::array<int, 2>& b) {
return a[1] < b[1]; };
int two_dim[][2] = {{1, 8}, {2, 4}, {3, 10}, {4, 40}, {5, 1}};
std::array<std::array<int, 2>, 5>& arr =
*reinterpret_cast<std::array<std::array<int, 2>, 5>*>(&two_dim);
std::sort(arr.begin(), arr.end(), two_dim_less);
for (int i = 0; i < 5; i++)
std::cout << two_dim[i][0] << ", " << two_dim[i][1] << '\n';
return 0;
}
Output:
5, 1
2, 4
1, 8
3, 10
4, 40
Regarding the use of std::qsort(), note that it is potentially slower than std::sort() due to the latter allowing to inline the comparisons while the former doesn't.
std::sort() requires the objects it's used to sort to be MoveAssginable.
Arrays are not MoveAssginable (nor assignable at all).
Try using an array of structures or std::pairs instead.

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.

Sort 2 dimensional c array with std::sort

I cannot seem to sort a 2 dimensional c array with std::sort. I can however sort a one dimensional array. This is in a case where I am being handed a c array in a c++ program and am hoping to sort without copying it over to a std::array. Maybe there is some way to turn it into a std::array without copying it? That sounds doubtful to me as any std::array would then call a destructor on memory that it does not own.
Sorting One dimensional c style array works just fine:
int len = 5;
auto one_dim_less = [](int a, int b){
return a < b;
};
int one_dim[] = {4, 0, 3, 1, 2};
std::sort(one_dim, one_dim + len, one_dim_less);
Attempting to sort two dimensional c style array by second number does not compile:
int len = 5;
auto two_dim_less = [](int a[2], int b[2]){
return a[1] < b[1];
};
int two_dim[][2] = {{1,8}, {2,4}, {3,10}, {4,40}, {5,1}};
std::sort(two_dim, two_dim + len, two_dim_less);
Maybe there is some way to turn it into a std::array without copying
it?
Perhaps not turning into a std::array per se, but an alternative approach might be to cast the 2D C-style arrays into a std::array reference just for the sorting. Doing so in reliance on the standard saying an std::array representation in memory at least begins with its C-style array equivalent. See here under [array.overview§2]:
An array is an aggregate that can be list-initialized with up to N
elements whose types are convertible to T.
In practice, the following usage of reinterpret_cast is most probably safe, but do note that unless there is a special exception for it somewhere in the standard, it would formally be undefined behaviour:
#include <algorithm>
#include <array>
#include <iostream>
int main() {
auto two_dim_less = [](std::array<int, 2>& a, std::array<int, 2>& b) {
return a[1] < b[1]; };
int two_dim[][2] = {{1, 8}, {2, 4}, {3, 10}, {4, 40}, {5, 1}};
std::array<std::array<int, 2>, 5>& arr =
*reinterpret_cast<std::array<std::array<int, 2>, 5>*>(&two_dim);
std::sort(arr.begin(), arr.end(), two_dim_less);
for (int i = 0; i < 5; i++)
std::cout << two_dim[i][0] << ", " << two_dim[i][1] << '\n';
return 0;
}
Output:
5, 1
2, 4
1, 8
3, 10
4, 40
Regarding the use of std::qsort(), note that it is potentially slower than std::sort() due to the latter allowing to inline the comparisons while the former doesn't.
std::sort() requires the objects it's used to sort to be MoveAssginable.
Arrays are not MoveAssginable (nor assignable at all).
Try using an array of structures or std::pairs instead.

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

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)
{
....
}

Can i push an array of int to a C++ vector?

Is there any problem with my code ?
std::vector<int[2]> weights;
int weight[2] = {1,2};
weights.push_back(weight);
It can't be compiled, please help to explain why:
no matching function for call to ‘std::vector<int [2], std::allocator<int [2]> >::push_back(int*&)’
The reason arrays cannot be used in STL containers is because it requires the type to be copy constructible and assignable (also move constructible in c++11). For example, you cannot do the following with arrays:
int a[10];
int b[10];
a = b; // Will not work!
Because arrays do not satisfy the requirements, they cannot be used. However, if you really need to use an array (which probably is not the case), you can add it as a member of a class like so:
struct A { int weight[2];};
std::vector<A> v;
However, it probably would be better if you used an std::vector or std::array.
You cant do that simply.
It's better you use either of these:
vector <vector<int>> (it's basically a two dimensional vector.It should work in your case)
vector< string > (string is an array of characters ,so you require a type cast later.It can be easily.).
you can declare an structure (say S) having array of int type within it i.e.
struct S{int a[num]} ,then declare vector of
vector< S>
So indirectly, you are pushing array into a vector.
Array can be added to container like this too.
int arr[] = {16,2,77,29};
std::vector<int> myvec (arr, arr + sizeof(arr) / sizeof(int) );
Hope this helps someone.
Arrays aren't copy constructable so you can't store them in containers (vector in this case). You can store a nested vector or in C++11 a std::array.
You should use std::array instead of simple array:
#include <vector>
#include <array>
std::vector<std::array<int, 2>> weights;
std::array<int, 2> weight = {1, 2};
weights.push_back(weight);
or with a constructor:
std::vector<std::array<int, 2>> weights;
weights.push_back(std::array<int, 2> ({1, 2});
One possible solution is:
std::vector<int*> weights;
int* weight = new int[2];
weight[0] =1; weight[1] =2;
weights.push_back(weight);
Just use
vector<int*> .That will definitely work.
A relevant discussion on the same topic : Pushing an array into a vector
Situation like:
int arr[3] = { 1, 2, 3 };
std::vector<int[]> v;
v.push_back(arr);
doesn't work with error "cannot initialize array in vector with .."
This, could be worked well
int * arr = new int[3] { 1, 2, 3 };
std::vector<int*> v;
v.push_back(arr);
To instantiate the vector, you need to supply a type, but int[2] is not a type, it's a declaration.