How to push_back() C array into std::vector [duplicate] - c++

This question already has answers here:
Correct way to work with vector of arrays
(4 answers)
Closed 2 years ago.
This doesn't compile:
vector<int[2]> v;
int p[2] = {1, 2};
v.push_back(p); //< compile error here
https://godbolt.org/z/Kabq8Y
What's the alternative? I don't want to use std::array.
The std::vector declaration on itself compiles. It's the push_back that doesn't compile.

You could use a structure containing an array, or a structure containing two integers, if you really don't want to use std::array:
struct coords {
int x, y;
};
vector<coords> v;
coords c = {1, 2};
v.push_back(c);
alternatively, as mentioned, you could use a structure containing an array:
struct coords {
int x[2];
};
vector<coords> v;
coords c = {1, 2};
v.push_back(c);

Use std::array:
vector<std::array<int, 2>> v;
std::array<int, 2> p = {1, 2};
v.push_back(p);

I think you should check the C++ reference for vectors.
http://www.cplusplus.com/reference/vector/vector/vector/
You can see in the example, there is explained every way you can initialize a vector.
I think that for your case you need to do:
std::vector<int> v({ 1, 2 });
v.push_back(3);

As an alternative, as you explicitly state that std::array is not to be used, you could use pointers, it's kind of an oddball solution but it would work:
#include <iostream>
#include <vector>
int main()
{
const int SIZE = 2;
std::vector<int*> v;
static int p[SIZE] = {1, 2}; //extended lifetime, static storage duration
int *ptr[SIZE]; //array of pointers, one for each member of the array
for(int i = 0; i < SIZE; i++){
ptr[i] = &p[i]; //assign pointers
}
v.push_back(*ptr); //insert pointer to the beginning of ptr
for(auto& n : v){
for(int i = 0; i < SIZE; i++){
std::cout << n[i] << " "; //output: 1 2
}
}
}

Related

How do I append 10 arrays to form a single array in c++?

Let's say I have these 10 previously declared arrays in my code.
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int arr2[] = {1,2,3,4,5,6,7,8,9,10};
int arr3[] = {1,2,3,4,5,6,7,8,9,10};
int arr4[] = {1,2,3,4,5,6,7,8,9,10};
int arr5[] = {1,2,3,4,5,6,7,8,9,10};
int arr6[] = {1,2,3,4,5,6,7,8,9,10};
int arr7[] = {1,2,3,4,5,6,7,8,9,10};
int arr8[] = {1,2,3,4,5,6,7,8,9,10};
int arr9[] = {1,2,3,4,5,6,7,8,9,10};
int arr10[] = {1,2,3,4,5,6,7,8,9,10};
Basically, I want to append all 10 of these arrays one after another to make one single array.
ArrayOfArrays = { arr1[], arr2[], arr3[], arr4[], arr5[], arr6[], arr7[], arr8[], arr9[], arr10[] }
How would I go about doing this? This question might seem trivial for some, but I'm new to C++ and can not figure out how to do it. Please help and thanks in advance.
Basically, I want to append all 10 of these arrays one after another to make one single array.
You cannot do that.
The closest you can get to that is by using std::array.
std::array<int, 10> arr1 = {1,2,3,4,5,6,7,8,9,10};
...
std::array<int, 10> arr10 = {1,2,3,4,5,6,7,8,9,10};
std::array<std::array<int, 10>, 10> arrayOfArray = {arr1, ..., arr10};
Try this approach:
#include <iostream>
#include <vector>
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// ...other arrays here...
// We pass a reference to a vector and return the same vector for performance reasons.
// Compiler often can optimize that into a better code.
std::vector<int> append(std::vector<int> & vec, int * data, int size)
{
for (int i = 0; i < size; ++i)
vec.push_back(data[i]);
return vec;
}
int main()
{
std::vector<int> data;
data = append(data, arr1, 10);
data = append(data, arr2, 10);
for (auto i : data)
std::cout << i << ", ";
std::cout << std::endl;
return 0;
}
Also, in C++ there are good containers for storing arrays, try searching for std::array and std::vector containers. First is a fixed size static array, the other one is dynamic.
I want to append all 10 of these arrays one after another to make one
single array ?
You can have array of pointers like
int *ArrayOfPointers[10] = { &arr1, &arr2, &arr3, &arr4, &arr5, &arr6, &arr7, &arr8, &arr9, &arr10};
Here ArrayOfPointers is array of 10 int pointers i.e it can store address of 10 one dimension int array like arr1, arr2 etc.
I assume there may be better method than what I'm suggesting in advance C++ for the same task.
In C++ it is unnecessary and ill-advised to use C-style arrays. For arrays of
constant size you may use std::array
and for arrays of variable size, std::vector
It looks rather as if what you actually want is a constant two-dimensional matrix
and to be able to access each of its rows as as a constant array, but do not
know how to initialise a two-dimensional matrix. If that's the case, here's how:
#include <iostream>
#include <array>
std::array<std::array<int,10>,10> matrix = {{
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}}
}};
int main()
{
std::array<int,10> const & arr0 = matrix[0];
for (int const & i : arr0) {
std::cout << i << ' ';
}
std::cout << std::endl;
// Or more simply...
auto const & arr5 = matrix[5];
for (auto const & i : arr5) {
std::cout << i << ' ';
}
std::cout << std::endl;
}
Compile, link and run:
$ g++ -Wall -Wextra main.cpp && ./a.out
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
live demo

Get sparse subset of array as references

Is it possible to get a sparse (non-contiguous) subset of references to array elements?
Suppose I have array a = [1,4,5] and indices pos = [0,1]. I would like to get b = [1,5] without copying elements from a. In other words, I would like to slice into a and create a view called b.
The following errors since "expression is not assignable":
#include <array>
int main() {
std::array<double,3> a = {1, 4, 5};
std::array<double, 2> b;
int c = 0;
int pos[2] = {0,2};
for (auto i = a.begin(); i != a.end(); i++) {
&b[c] = i;
i++;
}
return 0;
}
You can't have direct references in a container. However, if you have access to C++11 you can use std::reference_wrapper:
#include <iostream>
#include <functional>
#include <vector>
#include <array>
int main() {
std::array<double,3> a = {1, 4, 5};
std::vector<std::reference_wrapper<double>> b;
int pos[2] = {0,2};
for (unsigned int i = 0; i < sizeof(pos) / sizeof(pos[0]); ++i)
{
b.emplace_back(a[pos[i]]);
}
for(const auto& viewer: b)
{
std::cout << viewer << "\n";
}
}
Otherwise, just use double*.
C++ Standard 8.3.2/4:
There shall be no references to references, no arrays of references,
and no pointers to references.
Answered here
However you can have a container array of a class with a referance member (initlized on constractor) and implement a =operator, if it's worth the effort

C++: Change value of variable using its pointer

Let's say I have the following funciton:
void part(T* arr){
//some function
int x[5] = {1,2,3,4,5};
arr = x;
}
where original:
int arr[5] = {0,0,0,0,0}
I would like to know, how can I change the value of original arr inside the function to be some other value (lets say x)?
Thanks
To achieve this, you would need to copy elements from the array x to arr:
std::copy(x, x + sizeof(x) / sizeof(x[0]), arr);
However, as a general advice, don't use raw pointers to represent an array of objects. You could use std::array instead and then you can use it's operator= to copy all elements.
#include <iostream>
#include <array>
void part(std::array<int, 5>& arr)
{
std::array<int, 5> x {{1, 2, 3, 4, 5}};
arr = x;
}
int main()
{
std::array<int, 5> arr;
part(arr);
for (const auto& val : arr) {
std::cout << val << " ";
}
}
LIVE
You were close.
void part(T* arr){
//some function
int x = 5;
*arr = x;
}
You just need to add a * in front of arr which means the value pointed to by that pointer. If you just say arr that means the actual address which you do not want to be changing.
Looks like you changed the question while I was writing my answer.
In this case you need a loop.
void part(T* arr){
//some function
int x[5] = {1,2,3,4,5};
for(int i = 0; i < 5; i++)
{
arr[i] = x[i];
}
}

copying a static array to dynamic array

I am defining a dynamic array in c++:
double *values;
int size = 5;
values = new (nothrow) double[size];
I know this works because it compiles, but I see some potential problems.
Say I want to assign values to this array:
double samples = [1,2,3,4,5,6];
values = samples; //runtime error: free or corruption
What exactly is happening to generate this error?
You should use std::copy to copy a static array to a dynamic array like the example below:
#include <iostream>
#include <algorithm>
int main() {
int *a = new int[5];
int b[] = {1, 2, 3, 4, 5};
std::copy(b, b + 5, a);
for(std::size_t i(0); i < 5; ++i) std::cout << a[i] << " ";
std::cout << std::endl;
return 0;
}
LIVE DEMO
Alternatively if you want the convenience of assignments instead of element-wise copying and provided that you know the size of the arrays in compile time and your compiler supports C++11 features, use std::arrays like the example below:
#include <iostream>
#include <array>
int main() {
std::array<int, 5> a;
std::array<int, 5> b {{1, 2, 3, 4, 5}};
a = b;
for(auto i : a) std::cout << i << " ";
std::cout << std::endl;
return 0;
}
LIVE DEMO
However, it is recommend to prefer std::vector over the use of raw dynamic arrays like the example below:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> a(5);
int b[] = {1, 2, 3, 4, 5};
std::copy(b, b + 5, a.begin());
for(auto i : a) std::cout << i << " ";
std::cout << std::endl;
return 0;
}
LIVE DEMO
It doesn't work because you're assigning a static array to a pointer.
double *values;
double samples[] = {1,2,3,4,5,6};
They're two different data types as far as the compiler is concerned.
When you say:
values = new double[size];
You're creating a block of heap (dynamic) memory, and "values" holds the memory address of the first element in the array. To fill in the values from your static array, you need to assign each element individually like so:
values[0] = samples[0];
values[1] = samples[1];
// or better yet
for (int i = 0; i < size; i++)
values[i] = samples[i]
You can use a std::vector which has an iterator constructor, this will solve the problem for you.
std::vector<double> values(std::begin(samples), std::end(samples));
This will ensure the heap memory is properly cleaned up, even in the case of exception, and employs the implementation's debugging machinery to help protect you from events like buffer overflow.

Pushing an array into a vector

I've a 2d array, say A[2][3]={{1,2,3},{4,5,6}}; and I want to push it into a 2D vector(vector of vectors). I know you can use two for loops to push the elements one by on on to the first vector and then push that into the another vector which makes it 2d vector but I was wondering if there is any way in C++ to do this in a single loop. For example I want to do something like this:
myvector.pushback(A[1]+3); // where 3 is the size or number of columns in the array.
I understand this is not a correct code but I put this just for understanding purpose. Thanks
The new C++0x standard defines initializer_lists which allows you to:
vector<vector<int>> myvector = {{1,2,3},{4,5,6}};
gcc 4.3+ and some other compilers have partial C++0x support.
for gcc 4.3+ you could enable c++0x support by adding the flag -std=c++0x
Its not the best way to have your static data represented like that. However, if your compiler vendor supports C++ tr1 then you could do:
#include <tr1/array> // or #include <array>
...
typedef vector<vector<int> > vector2d;
vector2d myvector;
// initialize the vectors
myvector.push_back(vector<int>());
myvector.push_back(vector<int>());
typedef std::array<std::array<int, 3>, 2> array2d;
array2d array = {{1,2,3},{4,5,6}};
array2d::const_iterator ai = array.begin(), ae = array.end();
for (vector2d::iterator i = myvector.begin(), e = myvector.end()
; i != e && ai != ae
; i++, a++)
{
// reserve vector space
i->reserve(array.size());
// copy array content to vector
std::copy(ai.begin(), ai->end(), i->begin());
}
You can use vector::assign (pointers to array elements are valid iterators):
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
std::vector<std::vector<int> > v(2);
for (size_t i = 0; i < 2; ++i)
v[i].assign(a[i], a[i] + 3);
This is a little tricky, but you could use template recursion to help you in having the assignment done almost completely at compile-time. I understand that's not exactly what you are looking for, but I think it's worthwhile :-)
Here's the code:
#include <vector>
using namespace std;
typedef vector<vector<int> > vector2d;
template<size_t K, size_t M, size_t N>
struct v_copy {
static void copy(vector2d& v, int(&a)[M][N])
{
v[K - 1].assign(a[K - 1], a[K - 1] + N);
v_copy<K - 1, M, N>::copy(v, a);
}
};
template<size_t M, size_t N>
struct v_copy<1, M, N> {
static void copy(vector2d& v, int(&a)[M][N])
{
v[0].assign(a[0], a[0] + N);
}
};
template<size_t M, size_t N>
void copy_2d(vector2d& v, int(&a)[M][N])
{
v_copy<M, M, N>::copy(v, a);
}
int main()
{
int A[2][3] = {{0, 1, 2}, {10, 11, 12}};
vector2d vector(2);
copy_2d(vector, A);
}
it needed a struct because in C++ you can't do partial specialization of functions. BTW , compiling it with gcc version 4.5.0, this code produces the same assembly as
vector[1].assign(A[1], A[1] + 3);
vector[0].assign(A[0], A[0] + 3);
It should not be very hard to have it compile with different types of 2-dimensions arrays.
If you want to push the data into vector of vectors, you have to write something like this:
vector<int> inner;
vector< vector<int> >outer;
...
outer.pushback(inner);
I think there is no way to do it in a single loop.
If you want to use just one vector (something similar like you written), then you can do it in a single loop:
int A[2][3]={{1,2,3},{4,5,6}};
int* p = A[0];
std::vector<int> inner;
std::vector< std::vector<int> >outer;
for(int i = 0; i < 6; ++i)
{
inner.push_back(*p++);
}
It's kind of cheating, but you could take advantage of the vector constructor to do one of the loops for you:
#include <vector>
int main() {
const int XMAX = 2, YMAX = 3;
int A[XMAX][YMAX] = {{1,2,3}, {4,5,6}};
std::vector<std::vector<int> > v;
for (size_t x = 0; x < XMAX; ++x) {
v.push_back(std::vector<int>(&A[x][0], &A[x][YMAX]));
}
}
You can resize vectors and then use copy.
int A[2][3]={{1,2,3},{4,5,6}};
std::vector< std::vector<int> > vec;
vec.resize(2);
for (int i=0; i<2; i++)
{
vec[i].resize(3);
std::copy(A[i], A[i]+3, vec[i].begin());
}
Is it practical? Definetly not.
Hm... I can produce a partial answer but not a full one.
int elementCount = 6; // I wonder if this can be done somehow with sizeof(A) * sizeof(A[0])
int* end = A + elementCount;
for(int* current = A; current < end; ++current) {
myvector.pushback(*current);
}
No. The only thing you can do is leverage existing loop functions so that you only have to write one or zero of your own loops.