copying a static array to dynamic array - c++

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.

Related

How to assign elements of array to a pointer pointing to an allocated array

#include <iostream>
int main() {
int arr[3] = {10, 11, 12};
int *p_arr = new int[3];
*p_arr = *arr; // This is how I assign, does not work
std::cout << *(p_arr+1); // Not results 11
}
I want to avoid the pointer pointing to the static array so I would assign or copy the static array elements to new allocated array. Is there a way to do this directly without iteratively assign it?
Actually someone in the comment, nick, helped me answer. std::copy might be the answer. Even though it still uses an iterative way, still better to use it rather than creating the code.
#include <iostream>
int main() {
int arr[3] = {0, 1, 2};
int *p_arr = new int[3];
int length = sizeof(arr)/sizeof(int);
std::copy(arr+0, arr+length, p_arr+0); // Copy elements
cout << sizeof(arr[0])/sizeof(int) << endl << *(p_arr+2);
}

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

How do you use a vector in c++?

I am a beginner in c++ and I am trying to understand vectors.
I know the basic format which is:
vector <dataType> vectorName;
People are telling me that vectors are like arrays. But, what I don't
understand is that for arrays you can do this:
array[] = {1, 2, 3}
But for vectors you don't seem to get to set it to a list. Or do you have
to keep using .push_back().
Also, can you use something like vectorName[1] or not?
Can anyone explain this to me?
Thanks.
You can use the style if you use C++11 or later.
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> vec = {1, 2, 3};
std::cout << vec[1] << std::endl;
return 0;
}
The whole purpose of vectors is to be "infinite", so you don't have to redefine it everytime you need to expand it.
push_back is made so you can add/expand to the array without redefining it; you still access and modify like a normal array:
std::vector<int> a;
a.push_back(2);
a.push_back(6);
std::cout << a[0] << std::end; //2
std::cout << a[1] << std::end; //6
a[0] = 5;
a[1] = 7;
std::cout << a[0] << std::end; //5
std::cout << a[1] << std::end; //7
You can also initialize it old-school style (the = is optional):
std::vector<int> a {2, 6};
std::cout << a[0] << std::end; //2
std::cout << a[1] << std::end; //6
Try this for C++:
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> vec { 34,23 };
return 0;
}
Or even:
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> v(2);
v = { 34,23 };
return 0;
}
seems non of the above gave you any hint on dealing with the vector after you created it, so, let's say you created it with few initial values.
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> vec { 34,23 };
// use push_back(some_value) if you have multiple values to put inside, say 1000.
// instead of using the index [] brackets, try .at() method
std::cout << vec.at(1) << std::endl;
// use both the .size() or the new syntax to loop over it
for (unsigned i = 0 ; i < vec.size() ; i++){
std::cout << vec.at(i) << std::endl;
}
// or the new syntax
for (auto & i : vec){
std::cout << i << std::endl;
}
return 0;
}
Have fun :)
Vectors are expandable arrays. Unlike an array, you are not restricted to the size you initialized it with.
Growth of vector: the vector doubles it size whenever you overflow it. Underneath the hood its still an array but the "expandable" property of it comes by copying the contents of the previous array into a new larger array.
Few things that you can do with vectors in C++
Initialization of vector
vector<Type> one (size, defaultValue);
vector<Type> two (one); // makes a new vector *two* with the contents of *one*
vector<int> three {1,2,3}; // using initializer list
Accessing an element
int temp = three[2]; //array like syntax
int temp = three.at(2);
You cannot increase the size of a vector using this syntax i.e. you cannot dothree[3]=4;
Expanding
three.pusk_back(4);
Shrinking
three.pop_back();

How can I declare an array from the size of a vector?

I am trying to copy a vector into an array however I don't know how to declare the array from the size of the vector.
Code:
int main() {
vector<int> ivec = {1, 2, 3, 4, 5};
constexpr size_t size = ivec.size();
int arr[size];
for(size_t i = 0; i < ivec.size(); ++i)
arr[i] = ivec[i];
for(size_t i : arr)
cout << i << endl;
return 0;
}
However, I think this won't compile because ivec.size() can't be a constant expression (though I'm not sure if this is the case). In which case how could I do this without having to manually enter the number of elements?
As of right now std::vector size() is not a constexpr, so you cannot use it in constexpressions. As a result, you can try using the new keyword for dynamically sized arrays, but that would be pointless, as you're already using a vector.
vector<int> vi = {1, 2, 3, 4, 5};
int* arr = new int[vi.size()];
std::copy(vi.begin(), vi.end(), arr);
for (unsigned int i = 0; i < vi.size(); i++)
std::cout << arr[i] << " ";
delete[] arr;
Note:: You can use std::begin() with the second example because arr[] is an array but not with the first example because arr* is a pointer. However, std::copy() accepts both, so it should be fine.
initializer_lists can be used in constexpressions:
constexpr initializer_list<int> il = {1, 2, 3, 4, 5};
int arr[il.size()];
std::copy(il.begin(), il.end(), std::begin(arr));
for (unsigned int i = 0; i < il.size(); i++)
std::cout << arr[i] << " ";
In general, it is not possible to copy a vector into array, because, a usual array is constexpr, while vector size is not, it is of dynamic size. There are also dynamic arrays supported by some compilers, but then again, there size is never constexpr.
I guess, you need just to use vector.
I don't know your motivation, but...
int main() {
vector<int> ivec = {1, 2, 3, 4, 5};
constexpr size_t size = ivec.size();
int* arr = (int*)malloc( sizeof( int * size ) );
for(size_t i = 0; i < ivec.size(); ++i)
arr[i] = ivec[i];
for(size_t i : arr)
cout << i << endl;
free( arr );
return 0;
}
You need to allocate memory, because as you have said vector size is not a constant:
int main() {
vector<int> ivec = { 1, 2, 3, 4, 5 };
size_t size = ivec.size();
int *arr = new int[size]; // allocate memory
for (size_t i = 0; i < ivec.size(); ++i)
arr[i] = ivec[i];
for (size_t i = 0; i < size; ++i)
cout << i << endl;
delete [] arr; // release memory
return 0;
}
It seems you want to get hold of the number of the elements in an initializer list yielding a constexpr. The only way I'm aware of doing this is to use
#include <cstddef>
template <typename T, std::size_t N>
constexpr std::size_t size(T(&)[N]) {
return N;
}
int main() {
int vec[] = { 1, 2, 3, 4, 5 };
constexpr std::size_t s = size(vec);
int array[s];
std::copy(std::begin(vec), std::end(vec), array);
}
If you really need to use a std::vector<T> as source, you'll need to allocate memory, probably using std::vector<T> in the first place! If you want to allocate the memory yourself you'd use it something like this:
std::vector<int> vec = { 1, 2, 3, 4, 5 };
std::unique_ptr<int[]> array(new int[vec.size()]);
std::copy(vec.begin(), vec.end(), array.get());
The use of std::unique_ptr<int[]> makes sure that the allocated memory is released automatically.
A constexpr is a Constant Expression which is an expression that is evaluated at compile-time. That it is known at compile-time is a fundamental trait of a constexpr.
Given this, you can see how it makes no sense to try to construct a non-dynamically-allocated C-style array at run time when the number of elements will only be known at run-time. The two ideas are orthogonal.
From a technical standpoint, you cannot initialize a constexpr from a non-constant-expression. vector::size() is non-constexpr, so as you suspect, it is not only not compilable, but it is also not logical from a design standpoint to try to construct a constexpr from it:
constexpr size_t size = ivec.size(); // NO GOOD!
All this being said, it's very rare to need to construct a C-style array from vector. You're already doing the Right Thing by using vector in the first place. Don't mess it all up now by copying it to a crappy array.
A vector is guaranteed to have contigious storage. What this means is you can use it just like a C-style array in most cases. All you need to do is pass the address (or reference) to the first element in the vector to whatever is expecting a C-style array and it will work just fine.
void AincentApiFunction (int* array, size_t sizeofArray);
int main()
{
std::vector <int> v;
// ...
AincentApiFunction (&v[0], v.size());
}
I'd avoid
constexpr size_t size = ivec.size();
int arr[size];
and do it like this
size_t size = ivec.size();
int* arr = new int[size];
and then you handle it like the constantly allocated array. Read more about dynamically allocated arrays.
and don't forget to
delete[] array;
In C++11 arrays may declared as runtime bound on the stack:
(Note: this is only per the latest available draft: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf and will likely not be standard, but g++ with -std=c++11 will allow it
Note that is is not constexpression:
8.3.4 Arrays [dcl.array]
D1 [ expressionopt] attribute-specifier-seqopt
Example from the standard:
void f(unsigned int n) {
int a[n]; // type of a is “array of runtime bound of int”
}
So all you need to do is remove constexpr:
int main() {
vector<int> ivec = {1, 2, 3, 4, 5};
size_t size = ivec.size(); // this is fine
int arr[size];
for(size_t i = 0; i < ivec.size(); ++i)
arr[i] = ivec[i];
for(size_t i : arr)
cout << i << endl;
return 0;
}
Your compiler may or may not allow this, so depends on how strictly standard you need to be