how to correctly use a dynamic array? - c++

So I am trying to use a dynamic array for my program and I do not know if I am doing it right. Should I use const int or just an int only?
int size = 1;
int *num1 = new int [size];
int *num2 = new int [size];
or
const int size = 1;
int *num1 = new int [size];
int *num2 = new int [size];

If the size is a compile-time constant that you want to create an "array" from, then I suggest std::array, as in
std::array<int, 1> num1;
If the size isn't known at compile-time then use std::vector, as in
std::vector<int> num1(size);
And if you really have to use explicit dynamic allocation then opt for smart pointers like std::unique_ptr, like
auto num1 = std::make_unique<int[]>(size);
As for if the variable size should be const, constexpr, not qualified at all, or if you should possible use the literal value directly when allocating, then it really depends on use-case, value availability, and personal preference.
On another note, for a size you should rather use the size_t type instead of int. Most programmers will immediately understand that when you use size_t the variable is used to store a size. Otherwise if you use int it could be any arbitrary integer value. Furthermore, size_t is an unsigned type, so it doesn't allow negative numbers, which is one less cause of problems.

I've seen you ask a few questions about this now, so I want to show you the difference between having to resize a dynamic array and using std::vector, which packages all of the features you'd want in a dynamically-sized block of contiguous memory.
The following code is how to increase a dynamic array to hold user input. We don't know how long the user wants to input numbers for, so we have to keep resizing every time they enter a new number.
int number = 0;
std::size_t array_size = 0; // we need to track the size of the thing
int *array = nullptr; // nothing in here yet
std::cout << "Enter a number, non-number to exit: ";
while (std::cin >> number)
{
// we need to request more memory
++array_size;
int *new_array = new int[array_size];
// we have to copy the old array to the new array
// fun note: as pointed out in the comments below, using memcpy on
// either src or dest == nullptr is undefined behavior. Just goes to
// show how hard it is to get something like this correct.
// Don't do this when we have perfectly good STL containers!
std::memcpy(new_array, array, (array_size - 1) * sizeof(int));
// delete the old array, if it exists (we can safely call delete on a nullptr)
delete[] array;
// assign the new block of memory to array
array = new_array;
// add the retrieved element to array
array[array_size - 1] = number;
std::cout << "Enter a number, non-number to exit: ";
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// output the array
for (std::size_t i = 0; i < array_size; i++)
{
std::cout << array[i] << "\n";
}
// all done, delete the memory that was allocated
delete[] array;
array = nullptr; // not strictly required, but can prevent us from accidentally deleting the same block of memory twice, which would be bad
We can do the same thing using std::vector:
int number;
std::vector<int> vec; // this is a vector that holds ints, it tracks its own size and memmory
std::cout << "Enter a number, non-number to exit: ";
while (std::cin >> number)
{
vec.push_back(number); // all done
std::cout << "Enter a number, non-number to exit: ";
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
for (std::size_t i = 0; i < vec.size(); i++)
{
std::cout << vec[i] << "\n";
}
// or we can used range-based for loops, which are awesome
for (auto& v : vec)
{
std::cout << v << "\n";
}
Note that in the std::vector example, I'm outputting the contents of the std::vector twice, just to show that we have an option for iterating through a vector that is not available for an int *. We don't need to keep track of memory. We don't need to new and delete. When the current program scope exits (if this is a function, for example), the destructor of the std::vector is called and cleans up memory for us.
USE VECTORS!!!

Related

how to use delete keyword correctly to avoid memory leaks in c++

I see this code in geek for geeks and it has memory leak on 58 line as guided by valgrind ,
i don't see any way how to fix this to make it a better code, cause if we delete that new then assigned v[i] also delete and no value get inside it !!
i am a beginner to coding!!
here is the code
// C++ Program to create
// vector of pointer
#include<bits/stdc++.h>
using namespace std;
void insert_element(vector<int*>& v, int i)
{
// declaration and input of values of elements
int a;
cin >> a;
// allocating address to i element
v[i] = new int(a);
}
void print_vector(vector<int*>& v)
{
// printing elements of the vector
for (int i = 0; i < v.size(); i++) {
cout << *(v[i]) << " ";
}
cout << endl;
}
void delete_element(vector<int*>& v, int pos)
{
// Out of limit positions
if (pos <= 0 || pos > v.size())
return;
// converting position into index number
pos = pos - 1;
// free the space from pointer
delete v[pos];
// removing element from the vector
v.erase(v.begin() + pos);
}
int main()
{
cout << "Enter size of vector: ";
// size of vector
int n;
cin >> n;
// create a vector
vector<int*> v(n, nullptr);
cout << "Enter elements of vector: ";
for (int i = 0; i < n; i++) {
// inserting n elements inside v vector
insert_element(v, i);
}
cout << "Before: ";
// printing vector
print_vector(v);
cout << "Enter position to remove: ";
int pos;
cin >> pos;
// delete element from pos position
delete_element(v, pos);
cout << "After: ";
// printing vector
print_vector(v);
return 0;
}
i tried delete it but it says expected pointer in that place with delete keyword
error: type ‘class std::vector<int*>’ argument given to ‘delete’, expected pointer
15 | delete v;
The simplest way to avoid leaks is... not to use new\delete expressions anywhere outside of object construction and destruction. That's the part of RAII principle.
What valgrind reports, is that the function called on 58th line (insert_element) had created "leaked" free store memory, but that leak happens on exit from the main()function. The vector of pointers is destroyed, but the objects in free store aren't. In most cases it's a harmless scenario, but let be formal.
Our choices are
A.) Avoid extra allocation at all. It's not necessary here. we can use vector<int>. In this particular case it's a preferable solution. Usually the pointer's size is equal or greater in size than an int. Vector already works with free store.
B.) Use a vector that will delete elements automatically. Seriously, that's the responsibility of a container. But that would require multiple changes in code, because the type itself has changed. We can avoid that y declaring a type-alias.
// Use it everywhere in code.
using MyVector = std::vector<std::unique_ptr<int>>
That's not a great solution. We overengineered the container also we can't actually make a copy of it. The latter is true for original code - the vector isn't really copyable, a second copy would have pointers referring to same memory, but clearing one copy would cause pointers in the other copy to "dangle" - to point at invalid memory where object no longer exists.
You might need a smart pointer with reference counting instead -shared_ptr, even maybe a custom deleter and allocator. It's too much to store a single int.
C.) A "mechanist" solution: fix the problem by applying ducttape code where it is broken:
// printing vector
print_vector(v);
for( auto &item : v)
delete item;
return 0;
}
PS. Be sure it's not a "ducktape code", i.e. a fragile solution where you patch every hole and apply it everywhere. Aside from the copyright issues with Ducktape brand, a badly written code, while badly maintained, quickly becomes an unreadable mess where following fixes may be utterly wrong and the project falls apart. Especially if one who does fixing didn't wrote the original.

Dynamic memory Points in C++

I am trying to write code in C++ that reads from a file, a sequence of points, stores it in a dynamic array and then prints back.
This is the specification I've been given:
"We want to take advantage of the fact that we can use dynamic memory, thus instead of allocating at beginning an amount of memory large enough according to our estimations, we implement the following algorithm:
Initially, very little memory is allocated.
At each iteration of the loop (reading from the file and storing into the
dynamic array) we keep track of:
The array maximum size (the allocated memory).
The number of elements in the array.
When, because of a new insertion, the number of elements would become
greater than the array maximum size, memory reallocation needs to take
place as follows:
Allocate another dynamic array with a greater maximum size.
Copy all the elements from the previous array to the new one.
Deallocate the memory area allocated for the previous array.
Get the pointer to the previous array to point to the new one.
Add the new item at the end of the array. This is where my problem is.
From my code below, I think everything else is fine but the last requirement, which is to add the new item at the end of the array.
The code works fine when the array Max_Size exceeds file's number of
elements, but when I try extending the num_elements, the result is
that the extra digits in the file are just saved as zeros
.
Also to add, the assignment doesn't allow use of vectors just yet.
Sorry I forgot to mention this, I'm new to stackoverflow and somewhat
to programming.
Any help please
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct point {
double x;
double y;
};
int main () {
ifstream inputfile;
inputfile.open("datainput.txt");
if(!inputfile.is_open()){
cout << "could not open file" << endl;
exit(EXIT_FAILURE);
}
//initially very little memory is allocated
int Max_Size = 10;
int num_elements = 0;
point *pp = new point[Max_Size];
//read from file and store in dynamic array
for (int i = 0; !inputfile.eof(); i++) {
inputfile >> pp[i].x >> pp[i].y;
num_elements++; //keep track of number of elements in array
}
//detecting when number of elements exeeds max size due to new insertion:
if (num_elements > Max_Size){
// allocate another dynamic array with a greater maximum size
Max_Size *= 2; // Max_Size = 2*Max_Size to double max size whenever there's memory problem
point *pp2 = new point[Max_Size];
//copy all elements from previous array to new one
for (int j=0; j<(Max_Size/2); j++) {
pp2[j].x = pp[j].x ;
pp2[j].y = pp[j].y;
}
//deallocate memory area allocated for previous array
delete [] pp;
//get pointer to previous array to point to the new one
pp = pp2;
**//add new item at end of the array
for (int k = ((Max_Size/2)-1); k<num_elements; k++) {
inputfile.seekg(k, ios::beg) >> pp2[k].x;
inputfile.seekg(k, ios::beg) >> pp2[k].y;
}**
//print out dynamic array values
for (int l = 0; l<num_elements; l++) {
cout << pp2[l].x << ",";
cout << pp2[l].y << endl;
}
//delete dynamic array
delete [] pp2;
}
else {
//print out dynamic array values
for (int m = 0; m<num_elements; m++) {
cout << pp[m].x << ",";
cout << pp[m].y << endl;
}
//delete dynamic array
delete [] pp;
}
cout <<"Number of elements = " << num_elements <<endl;
//close file
inputfile.close();
return 0;
}
Others have already pointed out std::vector. Here's roughly how code using it could look:
#include <vector>
#include <iostream>
struct point {
double x;
double y;
friend std::istream &operator>>(std::istream &is, point &p) {
return is >> p.x >> p.y;
}
friend std::ostream &operator<<(std::ostream &os, point const &p) {
return os << p.x << "," << p.y;
}
};
int main() {
// open the file of data
std::ifstream in("datainput.txt");
// initialize the vector from the file of data:
std::vector<point> p {
std::istream_iterator<point>(in),
std::istream_iterator<point>() };
// print out the data:
std::copy(p.begin(), p.end(), std::ostream_iterator<point>(std::cout, "\n"));
}
On top of being a lot shorter and simpler than the code you posted, getting this to work is likely to be a lot simpler and (as icing on the cake) it will almost certainly run faster1 (especially if you have a lot of data).
1. In fairness, I feel obliged to point out that the big difference in speed will mostly come from using \n instead of endl to terminate each line. This avoids flushing the file buffer as each line is written, which can easily give an order of magnitude speed improvement. See also: https://stackoverflow.com/a/1926432/179910
The program logic is flawed. You run the loop until EOF but you don't check to see if you have exeeded your array size. I would add an if statement inside of the first loop to check if you have passed the Max_Size. I would also write a function to reallocate the memory so you can simply call that function inside of your first loop.
Also you have problems with your memory allocation. You should do like this:
point temp = pp;
pp = new Point[...];
// Copy the contents of temp into pp
delete temp;
You need to set your pointer to the old array first so you don't lose it. Then after you have copied the contents of you old array into the new array, you can then delete the old array.

How to a resize a dynamic array?

Let's say I have a dynamic array:
int* p;
ifstream inFile("pop.txt");
int x;
while (inFile >> x)
{
// ????
}
How do I resize p so I am able to to fit x in as like an array. I don't want to use a vector or static array as I am trying to learn the language. I need to use pointers because I don't know the initial size. Any attempt is appreciated.
The simplest answer is that you should use higher level components than raw arrays and raw memory for the reading. That way the library will handle this for you. A simple way of reading a set of numbers into an application (without error handling) could be done with this simple code:
std::vector<int> data;
std::copy(std::istream_iterator<int>(inFile), std::istream_iterator<int>(),
std::back_inserter(data));
The code creates a couple of input iterators out of the stream to read int values, and uses a back_inserter iterator that will push_back onto the vector. The vector itself will manage growing the memory buffer as needed.
If you want to do this manually you can, you just need to allocate a larger chunk of memory, copy the first N elements from the old buffer, release the old buffer and continue reading until the larger buffer gets filled, at which point you follow the same procedure: allocate, copy, deallocate old, continue inserting.
You can't resize it. All you can do is allocate a new bigger array, copy everything over from the old array to the new array, then free the old array.
For instance (untested code)
int array_size = 10;
int* array = new int[array_size];
int array_in_use = 0;
int x;
while (in >> x)
{
if (array_in_use == array_size)
{
int* new_array = new int[2*array_size];
for (int i = 0; i < array_size; ++i)
new_array[i] = array[i];
delete[] array;
array = new_array;
array_size *= 2;
}
array[array_in_use++] = x;
}
It's tedious, and I'm not convinced it's a good thing for a beginner to be doing. You'd learn more useful stuff if you learned how to use vectors properly.
You could always use realloc(). It's a part of the C Standard Library, and the C Standard Library is a part of the C++ Standard Library. No need for tedious news and deletes.
#include <cstdlib>
#include <iostream>
#include <fstream>
int main(void)
{
int* array = nullptr;
unsigned int array_size = 0;
std::ifstream input("pop.txt");
for(int x; input >> x;)
{
++array_size;
int* array_failsafe = array;
array = static_cast<int*>(realloc(array, sizeof(x) * array_size));
if(array == nullptr)
{
std::cerr << "realloc() failed!" << std::endl;
free(array_failsafe);
return EXIT_FAILURE;
}
array[array_size-1] = x;
}
for(unsigned int i = 0; i < array_size; ++i)
{
std::cout << "array[" << i << "] = " << array[i] << std::endl;
}
free(array); // Don't forget!
return EXIT_SUCCESS;
}

initializing a dynamic array to 0?

int main()
{
int arraySize;
int arrayMain[arraySize-1];
cout << "\n\nEnter Total Number of Elements in Array.\n\n";
cin >> arraySize;
arrayMain[arraySize-1]={0};
cout <<"\n\n" <<arrayMain;
return 0;
}
my compiler freezes when I compile the above code. I am confused on how to set a dynamic array to 0?
You use a std::vector:
std::vector<int> vec(arraySize-1);
Your code is invalid because 1) arraySize isn't initialized and 2) you can't have variable length arrays in C++. So either use a vector or allocate the memory dynamically (which is what std::vector does internally):
int* arrayMain = new int[arraySize-1] ();
Note the () at the end - it's used to value-initialize the elements, so the array will have its elements set to 0.
if you want to initialize whole array to zero do this ,
int *p = new int[n]{0};
If you must use a dynamic array you can use value initialization (though std::vector<int> would be the recommended solution):
int* arrayMain = new int[arraySize - 1]();
Check the result of input operation to ensure the variable has been assigned a correct value:
if (cin >> arraySize && arraySize > 1) // > 1 to allocate an array with at least
{ // one element (unsure why the '-1').
int* arrayMain = new int[arraySize - 1]();
// Delete 'arrayMain' when no longer required.
delete[] arrayMain;
}
Note the use of cout:
cout <<"\n\n" <<arrayMain;
will print the address of the arrayMain array, not each individual element. To print each individual you need index each element in turn:
for (int i = 0; i < arraySize - 1; i++) std::cout << arrayMain[i] << '\n';

Int Array Length C++

I have to use a dynamic length int array in my program, and want to be able to get the number of objects in it at various points in my code. I am not that familiar with C++, but here is what I have. Why is it not giving me the right length? Thanks.
<#include <iostream>
Using Namespace std;
int length(int*);
void main()
{
int temp[0];
temp[0] = 7;
temp [1] = 10;
temp[2] = '\0';
cout << length(temp) << endl;
}
int length(int* temp)
{
int i = 0;
int count = 0;
while (*temp + i != '\0')
{
count++;
i++;
}
return count;
}
currently it just goes into an endless loop ;_;
In C++ arrays are not dynamic. Your temp array has zero length, and attempting to write to members beyond its length is undefined behaviour. It's most likely not working as it will be writing over some part of the stack.
Either create a fixed size array with enough space to put everything you want to in it, or use a std::vector<int> which is a dynamic data structure.
#include <iostream>
#include <vector>
using namespace std;
int length(int*);
int main () // error: ‘::main’ must return ‘int’
{
int temp[3];
temp[0] = 7;
temp[1] = 10;
// don't use char constants for int values without reason
temp[2] = 0;
cout << length(temp) << endl;
vector<int> vec_temp;
vec_temp.push_back(7);
vec_temp.push_back(10);
cout << vec_temp.size() << endl;
}
int length(int* temp)
{
int i = 0;
int count = 0;
while (*(temp + i) != 0) // *temp + i == (*temp) + i
{
count++;
i++; // don't really need both i and count
}
return count;
}
For the vector, there's no need to specify the size at the start, and you can put a zero in, and finding the length is a simple operation rather than requiring a loop.
Another bug inside your loop was that you were looking at the first member of the array and adding i to that value, rather than incrementing the pointer by i. You don't really need both i and count, so could write that a couple of other ways, either incrementing temp directly:
int length(int* temp)
{
int count = 0;
while (*temp != 0)
{
++count;
++temp;
}
return count;
}
or using count to index temp:
int length(int* temp)
{
int count = 0;
while (temp[count] != 0)
++count;
return count;
}
This approach is a bad idea for a couple of reasons, but first here's some problems:
int temp[0];
This is an array of 0 items, which I don't even think is permitted for stack elements. When declaring an array like this you must specify the maximum number of values you will ever use: E.g. int temp[10];
This is super important! - if you do specify a number less (e.g. [10] and you use [11]) then you will cause a memory overwrite which at best crashes and at worst causes strange bugs that are a nightmare to track down.
The next problem is this line:
while (*temp + i != '\0')
That this line does is take the value stores in the address specified by 'temp' and add i. What you want is to get the value at nth element of the address specified by temp, like so:
while (*(temp + i) != '\0')
So that's what's wrong, but you should take five minutes to think about a better way to do this.
The reasons I mentioned it's a bad idea are:
You need to iterate over the entire array anytime you require its length
You can never store the terminating element (in this case 0) in the array
Instead I would suggest you maintain a separate value that stores the number of elements in the array. A very common way of doing this is to create a class that wraps this concept (a block of elements and the current size).
The C++ standard library comes with a template class named "vector" which can be used for this purpose. It's not quite the same as an array (you must add items first before indexing) but it's very similar. It also provides support for copying/resizing which is handy too.
Here's your program written to use std::vector. Instead of the 'length' function I've added something to print out the values:
#include <vector>
#include <iostream>
void print(std::vector<int> const& vec)
{
using namespace std;
for (size_t i = 0; i < vec.size(); i++)
{
cout << vec[i] << " ";
}
cout << endl;
}
int main()
{
std::vector<int> temp;
temp.push_back(7);
temp.push_back(10);
print(temp);
return 0;
}
You could try:
while (*(temp + i) != '\0')
Your current solution is calculating temp[0] + i (equals 7+i), which apparently is not what you want.
Not only C++ arrays are not dynamic as Pete points out, but only strings (char *) terminate with '\0'. (This is not to say that you can't use a similar convention for other types, but it's rather unusual, and for good reasons: in particular, relying on a terminator symbol requires you to loop through an array to find its size!)
In cases like yours it's better to use the standard library.
#include <vector>
#include <iostream>
int main()
{
std::vector<int> v;
v.push_back(7);
v.push_back(10);
std::cout << v.size() << std::endl;
return 0;
}
If you don't want to use std::vector, try this:
#include <iostream>
using namespace std;
int main () {
int vet[] = {1,2,3,4,5,6};
cout << (sizeof (vet) / sizeof *(vet)) << endl;
return 0;
}
The most common way to get the size of a fixed-length array is something like this:
int temp[256];
int len = sizeof (temp) / sizeof (temp[0]);
// len == 256 * 4 / 4 == 256 on many platforms.
This doesn't work for dynamic arrays because they're actually pointers.
int* temp = new int[256];
int len = sizeof (temp) / sizeof (temp[0]);
// len == 4 / 4 == 1 on many platforms.
For a dynamic-length array if you care about the size, you're best off storing it somewhere when you allocate the array.
The problem with your loop, as pointed out by many is that you have an operator precedence problem here:
*temp + i
should be:
*(temp + i)
But the bigger problem, also pointed out above, is that you don't appear to understand pointers versus fixed-length arrays and are writing off the end of your array.
If you want to use array properly, you have to allocate enough memory for storing values. Once you specified its length, you can't change it. To know array size, you should store it in variable e.g.:
int n;
cin>>n;
int array = new int[n];
int array_length=n;
If you want to change array's length, best way is to use std container, for example std::vector.
Here is the answer to your question
int myarr [] = {1, 2, 3, 4, 5};
int length = sizeof(myarr) / sizeof(myarr[0]);
cout << length;
Because you only allocate space for an array of zero elements.
The following lines
temp [1] = 10;
temp[2] = '\0';
do not allocate more memory or resize the array. You are simply writing data outside the array, corrupting some other part of the application state. Don't do that. ;)
If you want a resizable array, you can use std::vector (and use the push_back member function to insert new values)
A vector also has the size() member function which tells you the current size.
If you want to use the primitive array, you have to track the size yourself. (and, when resizing the array is necessary, copy all elements from the old array to the new, larger one)
To get dynamic behavior in arrays, use a std::vector, or fall back on the old school c style using int * with manual memory allocation (new and delete)[*]
[*] C implementations (discussed in the context of character arrays as C dynamic string length) used malloc, realloc, and free, but these should be avoided in c++ code.
Try this out:
int length(int* temp)
{
int count = 0;
while (*temp != 0 && *temp != -858993460)
{
++count;
++temp;
}
return count;
}