Changing my array definitions to Vectors or Lists? - c++

According to that question, I'm more and more worried about the management of the memory in my project, and my program would crash when there is somewhere a conflict in one of the array memories.
The different answers to this posted question have converged to the fact that I would change my arrays to Vectors and some of my arrays are defined as below:
#define Nb 50
int position[Nb];
double indication[Nb];
double sum[Nb];
how to change each one of them to
std::vector
std::list?
Can we manipulate / process them when changing their declaration (organizing them in ascending order for example or overwriting one of the values) ?

You are using fixed size arrays,
#define Nb 50
int position[Nb];
the modern C++ alternative to these is std::array, not std::vector:
std::array<int, 50> position;
std::vector is a dynamically sized array, whose size can be determined at runtime and can change after construction.
int n;
std::cin >> n;
std::vector<int> v(n); // vector has n value constructed ints
v.push_back(42); // v has n+1 ints now.
C++14 offers std::dynarray, which is a dynamically sized array, whose size can be determined at runtime but cannot be changed after construction.

The Syntax is as follows:
#define Nb 50
std::vector<int> position(Nb); // create std::vector holding ints, Initial size is 50
You should also refrain from using #define, but rather use const, this is more C++:
const int Nb = 50; //maybe wrap Nb in a namespace
std::vector<int> position(Nb);
See vector and its constructors.

Related

How to dynamically allocate a 2D std::array in C++ or why I should not use it?

I want to malloc an array in my code, and its size should be defined at runtime.
I tried like this:
#include <iostream>
#include <array>
int main(){
int M=4,N=3,P=5;
M=N+P;
std::array<std::array<double,M>,N> arr;
}
But MSVC told me:
a variable with non-static storage duration cannot be used as a non-type argument
I don't find the answer to this in stackoverflow.(The existing question seem not to solve my problem...)
How to dynamically allocate a 2D std::array in C++?
I know I could use std::vector to solve this. But the vector memory size needs to be organized by myself and this would be used many times in my project. And I want to use C++ type code rather than C type...Maybe there is a method to turn a 2D array in C type to std::array, but I can't find it by Google...
So I ask this question...
I mean the M and N should be got dynamically(not changed,but I can only know it in runtime...),like:
#include <iostream>
int main(){
int a=3;
int b=4;
int rowCount=a+b;
int colCout=b-a;
int** a = new int*[rowCount];
for(int i = 0; i < rowCount; ++i)
{
a[i] = new int[colCount];
}
}
I know where is my mistake. I fell into a logical question... If I don't use push_back,the vector works well. If I use it, the array doesn't work, too.
I think the capcity of vector is bigger than its size, I want to avoid this. But another question: How to limit the capacity of std::vector to the number of element show I should use my allocator or std::vector::shrink_to_fit() to avoid it...(There is no guarantee in C++17 if you use reserve(n))
The dynamically allocated array container in C++ is std::vector. std::array is for specifically compile-time fixed-length arrays.
https://cppreference.com is your friend!
But the vector memory size needs to be organized by myself
Not quite sure what you mean with that, but you specify the size of your std::vector using the constructor.
std::vector<std::vector<int>> arr(N);
If you need some special allocator (not just new/malloc), then you can also specify a custom allocator.
Your whole program that you propose is not good C++. A C++ solution would look like:
#include <vector>
int main() {
int a = 3;
int b = 4;
unsigned int rowCount = a + b;
unsigned int colCount = b - a;
std::vector<std::vector<int>> matrix(rowCount);
for (auto& row : matrix) {
row.resize(colCount);
}
}
std::array, like an actual array in C++, requires a constant size. It's what gives it any advantage at all over std::vector.
For a technical explanation as to how that requirement is implemented, remember that template parameters are required to be compile-time constants (since it changes how the code is generated, again at compile-time).
Anyway, you want to use std::vector here. If you know the size you want, give it as a constructor parameter.

Should I use vectors instead of arrays?

If I have a fixed number of elements of class MyClass, should I use arrays or vectors?, ie:
MyClass* myArray[];
or
std::vector<MyClass*> myVector;
?
Use std::array or raw arrays for a small, static number of elements.
If you have a lot of elements (more than say 100kb), you hog the stack and are asking for stack corruption / overflow. In that case, or if the number of elements can only be known at runtime, use std::vector.
if you know the number in compile time - use static array.
if the number is dynamic (obtained from the user) - vector is much better to save you the hurdle of managing the memory
"Fixed" has two meanings in this context. The usual one is set once, never change, such as a value read from input. This value is known at runtime and requires dynamic allocation on the heap. Your options are a C-style array with new or a vector; it is highly recommended you use a vector.
#include <vector>
#include <iostream>
int main() {
int size;
std::cin >> size;
int *myArray = new int[size];
std::vector<int> myVector(size);
}
"Fixed" can also mean a compile-time constant, meaning it is constant for any run of the program. You can use a C-style array or a C++ array (automatic memory allocation on the stack).
#include <array>
int main() {
const int size = 50;
int myArray[size];
std::array<int, size> myArray;
}
These are faster, but your program needs to have access to sufficient stack memory, which is something you can change in your project settings. See this topic for more info. If the size of the array is really big, you may want to consider allocating on the Heap anyway (vector).

Is there any built in method in c++ to findout length of an array?

like array.length in java is there any built in method in c++ to findout size of an array?
I know about length(). but it only works for strings only ...
And i tried this ...
int a[10];
a[0]=1;
a[1]=2;
print(sizeof(a)/size(a[0]))
but it gives output as 10 but is there a way getting only 2 as output
If you're using C++, don't use arrays, use std::vector instead (especially if you need the count of currently held items, not the container's capacity). Then you can write:
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
printf("%d\n", vec.size());
int a[10];
declares an array of 10 ints; sure, you're only initialising the first two, but the other 8 are still there, they're just (probably) filled with junk at the moment.
To do what you want, you should use a std::vector instead. You can then do this:
std::vector<int> a;
a.push_back(1);
a.push_back(2);
std::cout << a.size() << std::endl; // prints 2
Arrays in C/C++ do not store their lengths in memory, so it is impossible to find their size purely given a pointer to an array. Any code using arrays in those languages relies on a constant known size, or a separate variable being passed around that specifies their size.
In an array of 10 ints, when it is declared, memory is allocated for 10 int values. even if you initialize just two, the rest of it contains some junk values and the memory remains allocated.
If you want the used size, your best bet is to use std::vector.
if you want to know the number of elements in an array you can do this
int array[3] = {0, 1, 2};
int arraylength = sizeof(array)/ sizeof(*array);
Sure. It's name is vector::size. It doesn't apply to C-style arrays, only to std::vector. Note that Java's Array class is also not a C-style array.

C++ assign array of ints to an empty array of ints same size

I am very familiar with Java and this is allowed there. However it looks like it's not with C++. I'm getting an "invalid array assignment" when trying to assign valuesToGrab = updatingValues;.
//these are class attributes
int updatingValues[361] = {0};
int valuesToGrab[361] = {0};
//this is part of a function that is causing an error.
for (unsigned int i=0; i < 10; i++) {
//this fills values with 361 ints, and num_values gets set to 361.
sick_lms.GetSickScan(values,num_values);
//values has 361 ints, but a size of 2882, so I copy all the ints to an array
//of size 361 to "trim" the array.
for(int z = 0; z < num_values; z++){
updatingValues[z] = values[z];
}
//now I want to assign it to valuesToGrab (another program will be
//constantly grabbing this array, and it can't grab it while it's being
//populated above or there will be issues
valuesToGrab = updatingValues; // THROWING ERROR
}
I don't want to have to iterate through updatingValues and add it to valuesToGrab one by one, but if I have to I will. Is there a way I can assign it in one function with C++?
Thanks,
The standard idiom for copying in C++ is
#include <algorithm>
...
std::copy(values, values+num_values, updatingValues);
make sure updatingValues is large enough or you will get overruns and bad things will happen.
That said in C++ we generally use a std::vector for this sort of task.
#include <vector>
...
std::vector<int> updatingValues=values; //calls vectors copy constructor
I vector does everything an array does (including static initalization in C++11), but has a well define interface. with iterators, size, empty, resize, push_back and more.
http://en.cppreference.com/w/cpp/algorithm/copy
http://en.cppreference.com/w/cpp/container/vector
EDIT
It is also worth noting that you can combine vector and arrays.
std::vector<int> vect(my_array, my_array+10);
//or
std::vector<int> another_vector;
...
another_vector.assign(my_array, my_array+10);//delayed population
and visa-versa
std::copy(vect.begin(), vect.end(), my_array); //copy vector into array.
First of all, I don't think this will do what you're looking for because valuesToGrab = updatingValues; will overwrite your valuesToGrab every cycle of the outer loop.
Assuming you did want to do this though, and you didn't want to change to a vector:
std::copy(updatingValues, updatingValues+361, valuesToGrab);
will do it. You can treat a normal array just like a std:: container in any std::algorithm, the pointers count as random access iterators.
Rethink your design though, you shouldn't need to "trim" and you probably don't need to copy.
In C++, the idiomatic container to use in place of arrays is std::vector. With vector or with arrays, you can use the std::copy() function from the <algorithm> header, which is the preferred way of copying containers of any sort in C++. With vector:
std::vector<int> updatingValues, valuesToGrab;
// Ensure the vector has sufficient capacity to accept values.
updatingValues.resize(361);
// Copy values from the array into the vector.
std::copy(values, values + 361, updatingValues.begin());
// Source begin & end; Destination begin.
// Copy one vector to another.
valuesToGrab = updatingValues;
With arrays:
std::copy(valuesToGrab, valuesToGrab + 361, updatingValues);
Again with just arrays, if you are going for more of a C style, you can use the C standard library function memcpy(), from <cstdlib>:
memcpy(valuesToGrab, updatingValues, 361 * sizeof(int));
// Destination; Source; Number of bytes.
With memcpy() (and its cousin, memmove()), you must be careful about the size of the elements you’re copying; if you say 361 instead of 361 * sizeof(int), you’ll copy 361 bytes, not 361 ints’ worth of bytes—a big difference.
Keep in mind that arrays are implemented as pointers in C and C++.
In particular an array on the stack can be visualized as a pointer to a constant location in memory that has the capacity that you requested for the array. This memory is on the stack. When you try valuesToGrab = updatingValues, you could think of this as trying to copy the address of updatingValues to the variable valuesToGrab. This is NOT attempting a deep copy, which you seem to be attempting. However, valuesToGrab points to a constant location in memory and cannot be updated. The standard is a little more specific on this and explicitly forbids the assignment of arrays, which is why you're getting the specific error that you're seeing.
You will need to use a loop or something like std::copy or C's memcpy to copy the values from one array to the other.

Selecting size of vector of vectors

I have a class called Grid that declares a vector of vectors like this:
typedef vector<int> row;
typedef vector<row> myMatrix;
myMatrix sudoku_;
The constructor looks like this:
grid::grid() : sudoku_(9,9)
{
}
As you can see, the constructor is initializing it to be a 9x9 grid. How can I make it work so that the user is asked for a number, say n, and the grid is initialized n x n ?
vector has a constructor that allows you to initialize it to a certain size with copies of a given value:
grid::grid(size_t w, size_t h) : sudoku_(w, row(h)) {}
if you can, do not use vector.
Use this instead http://www.boost.org/doc/libs/1_42_0/libs/multi_array/doc/user.html
#gf has the absolute right answer for the question, but I'd question the use of vector here (rare for me). In the case of a sudoku grid the structure is fixed size, so you don't win by having easy dynamic allocation. By using a vector of 9 vectors, you have ten populated vector objects. Each one of these has at least one dynamic allocation, so ten calls to new. On top of that, on the implementation of std::vector I am most familiar with the object is 12 bytes (3 32-bit pointers), plus the heap allocation overhead. All of that to deal with a structure which can comfortably be represented in less than 100 bytes is overkill.