I was looking for uses for pointers and this turned out to be one of them. Dynamically allocating memmory. I am a little confused with the keyword new, and when adding [number] in the end. new int[3]. I do understand that this question might be bad. I'm only 13.
#include <iostream>
using namespace std;
int main() {
int* scores;
cout << "Enter top 3 scores: ";
//dynamically allocate memory
scores = new int[3];
for (int i = 0; i < 3; i++) {
"Enter score: ";
cin >> scores[i];
}
cout << endl << "Scores are: ";
for (int i = 0; i < 3; i++) {
cout << scores[i] << " ";
}
delete[] scores;
return 0;
}
A pointer is basically a variable pointing to a specific address in memory. An array is a group of variables allocated consecutively in memory. When you write scores = new int[3] you allocate a memory for three int-type variables and make the scores variable reference the first one's address. Now, when referencing the array fields: scores[i], you take the address of the first field of the array and you add the variable i, giving you the address of the ith element.
When you create an integer pointer, you create a memory that contains the address of another memory. So, when you use the keyword 'new' you are allocating memory and its address is then stored in that pointer. Initially, without any allocation, there is no data stored in that integer pointer.
This is similar to what it means when you do int array[size], however, at times dynamically allocated memory is required e.g. if you need to change the size of an array. If you declared an array without dynamic allocation, you can not change its size but when the help of dynamic memory allocation you can easily delete the previously allocated memory and allocate another memory that is larger. A basic example of where dynamic memory ('new' keyword) is used is when you create an array of the names of students in a class, initially, they might be just 15 students but after a month if they grow over 30 and the array you declared was of size 15 you can just use the 'delete' and 'new' keyword to increase the size.
Related
This is a snippet of code that I took from a bigger one. I need to figure out whether or not what I'm printing is garbage and how to change it for it to print the value I need.
I need it to print the value of int id instead of whatever it's printing. The output was 10813776 in this run and it, of course, changes whenever I change some code or relaunch DevC++.
The code is:
#include <iostream>
#include <memory> //Memory allocation (malloc)
using namespace std;
int main(){
int id = 0;
int nMemory = 0;
int * pMemory;
pMemory = (int *) malloc(20 * sizeof(int));
while(id < 20){
if (pMemory != NULL){
cout << "Numbers in memory: " << endl;
pMemory = new int[id];
nMemory = *pMemory;
cout << nMemory << endl;
}
id++;
}
delete pMemory;
return 0;
}
pMemory = new int[id];
nMemory = *pMemory;
The first line replaces the array you've malloc-ed with a new uninitialized one, and then tries to read from the first slot of that new array. You shouldn't be assigning directly to pMemory; maybe to pMemory[someIndex], but not to pMemory itself.
Are you trying to read from the pMemory array and assign it to nMemory? If so, change the lines above to this:
nMemory = pMemory[id];
Your entire loop should look more like this:
if (pMemory != NULL) {
cout << "Numbers in memory: " << endl;
while(id < 20) {
nMemory = pMemory[id];
cout << nMemory << endl;
id++;
}
}
Or, with a more idiomatic for loop:
if (pMemory != NULL) {
cout << "Numbers in memory: " << endl;
for (int i = 0; i < 20; i++) {
cout << pMemory[i] << endl;
}
}
(You're also going to have to initialize the array somewhere above this loop. I presume you do that in your real code, but if not: the code you posted allocates an array with malloc() but does not set the items to useful values. Make sure to set them to something meaningful before you then try to read and print them.)
This code is leaking the memory blocks you allocate with malloc() and new[].
You malloc() a block of memory and assign its address to pMemory, then you change pMemory to point at different memory addresses that are allocated with new[]. So you lose the ability to free() the malloc()'ed memory (you are not even trying to call free()).
And, this code is not freeing the memory allocated with new[] correctly. Memory allocated with new[] must be freed with delete[], not with delete. Worse, you are calling new[] 20 times in a loop, but calling delete only once after the loop. So, you are leaking 19 blocks of new[]ed memory, and have undefined behavior freeing 1 block.
Now, to answer your actual question, the code is printing out garbage because the memory you are allocating with new[] is uninitialized, so the data you are trying to print from that memory contains indeterminate values.
As I describe above, always there is 12 Byte gap by each row when I allocate 2 dimension array dynamically.
In that code, I expected ppa[1] to be 0x1005626e4. But result is 0x1005626f0. I know dynamic allocation may not allocated in contiguous space. But there is always at least 12 Byte gap.(Actually some times each row allocated in different space)
I know when allocate in heap, need some space for store information. Eg size, type..
Is that reason of 12 Byte? If someone know real reason of 12 Byte tell me about that.
Code
int** ppa;
ppa = new int*[3];
for (int i = 0; i < 3; ++i) {
ppa[i] = new int[5];
cout << "ppa[" << i << "]: " << ppa[i] << endl;
for (int j = 0; j < 5; ++j) {
cout << "&ppa[" << i << "][" << j << "]: " << &ppa[i][j] << endl;
}
cout << endl;
}
output
ppa[0]: 0x1005626d0
&ppa[0][0]: 0x1005626d0
&ppa[0][1]: 0x1005626d4
&ppa[0][2]: 0x1005626d8
&ppa[0][3]: 0x1005626dc
&ppa[0][4]: 0x1005626e0
ppa[1]: 0x1005626f0
&ppa[1][0]: 0x1005626f0
&ppa[1][1]: 0x1005626f4
&ppa[1][2]: 0x1005626f8
&ppa[1][3]: 0x1005626fc
&ppa[1][4]: 0x100562700
ppa[2]: 0x100562710
&ppa[2][0]: 0x100562710
&ppa[2][1]: 0x100562714
&ppa[2][2]: 0x100562718
&ppa[2][3]: 0x10056271c
&ppa[2][4]: 0x100562720
My Test Environment
OS: OSX 64bit system
IDE: Xcode
What you do is creating a jagged array where there's no requirement that sub-arrays have to be allocated contiguously.
You simply get what the memory allocator gives you.
As pointed out above, you are allocating references of 3 different 1-D arrays (to ppa[i]) afterwards. However, these 1-D arrays may be assigned any memory address in the memory(no specific pattern of 12byte gap). The only ensured thing is that the elements inside 3 of these 1-D arrays will be contiguous.
Note:- If you create array such as "int ppa[3][5]", then all the elements will be contiguous.
Probably some internal information about allocated block is stored there.
I try to create objects dynamically. Each object is a pointer in an array of pointers. The compiler gives me
error C4700: uninitialized local variable 'villages' used.
And I can not figure out how to fix it. I would be very grateful to all the helpers.
int villageAmount;
cout << "Defining villages:\n\nEnter how many villages do you want: ";
cin >> villageAmount;
Village **villages;
for (int i = 0; i < villageAmount; i++)
{
cout << "\nDefining village's details #" << i + 1 << ":\n";
villages[i] = new (nothrow) Village;
}
Village **villages;
you declared villages without initializing, so it contains garabage valaue.
for (int i = 0; i < villageAmount; i++)
{
cout << "\nDefining village's details #" << i + 1 << ":\n";
villages[i] = new (nothrow) Village;
}
right below, you access into it and writes. That's no no.
If you want to store pointer of village (i.e. type of Village*) dynamically, you also need to allocate them.
Village **villages = new Village*[villageAmount];
Or if amount is fixed,
Village *villages[10] = { nullptr, }; // 10, 12344, or whatever
villages memory is never allocated, you should use a vector or any sort of container (an array look fine here).
If you really want to allow the memory manually you could do something like :
Village **villages = new Village*[villageAmount];
Don't forget to free EVERY new, (If you only free villages, all the Village* that he contain will remain allocated.
Edit : someone else answered so I guess my answere is usless
I am creating int array using c++ and trying to get the length of it
int *masterArray;
int count = 0;
int a = 0;
int var = 0;
ifstream myfile("sample_10.txt");
if (myfile.is_open())
{
while(myfile.good())
{
string word;
while(getline(myfile, word))
{
count++;
}
cout << "count: " << count << endl;
masterArray = new int [count];
myfile.clear();
myfile.seekg(0);
while(getline(myfile, word, '\n'))
{
cout << word << " ";
istringstream ( word ) >> var;
masterArray[a] = var;
a ++;
}
}
}
name of the int array is master array, and after I add variables in the array
I do..
cout << "sizeof(masterArray) : " <<sizeof(masterArray);
which gives me 8, instead of 10.
I tried to print out all variables stored in the array and it gives me 10, which means all variables are stored correctly.
should I retrieve the length by doing
cout << "sizeof(masterArray) : " <<sizeof(masterArray) / sizeof(*masterArray);
??
Because that gives me 2 (obviously, cuz it is dividing 8 by 4)
Thanks
Your masterArray variable is of pointer type. I suppose you are on a 64bit machine, so the pointers are 8 bytes. That's why it gives you 8 when you do a sizeof().
There is no standard way of getting the size of an array, at least not that I know of. You have a count that you get from the user and allocate the array with. I guess it would be best to keep that and use it.
I would suggest to use std::vector in your case. Note, that in C++ it is a common practice to use vectors for any array-like objects. You should have very strong arguments if you want to manage dynamically allocated arrays by yourself.
You already got the length - it's count. It's the only way of knowing a length of dynamically allocated array, by manually keeping track of it. As others have pointed out, you only get a pointer to the first element if you allocate an array via new. sizeof(masterArray) will return the size of this pointer and it happens to be 8 bytes on your platform.
Im guessing you are using 64 bit computer? sizeof returns the size of the variable it given in this case a pointer in other words a memory address which in 64 bit computer is equal to 8 bytes. In order to find the length of the array in c you need to use another variable with the size of the array stored in it.
This
sizeof(masterArray);
gives you the size of an int*, which is 8 on your platform (or 64 bits, assuming an 8 bit char).
Looking at your code, it seems to me that you could use std::vector instead of the array, and add elements using the std::vector::push_back method. If you actually needed the length, you could get it from the size() method, but what you normally do with a vector is to iterate over its contents using it's begin and end iterators (see methods begin() and end() respectively).
Using sizeof to get the number of elements in an array will only work for variables that are declared as arrays. E.g. int masterArray[10];.
Your array is declared as an int * - later allocated dynamically - so you're getting the size of that type.
sizeof() only works on arrays. You're getting 8 because a pointer is 8 bytes (on a 64 bit system). You cannot determine the length of a dynamically allocated array. This means that you need to keep track of the length, rather than re-determining it.
By the way, this looks like a very good situation to use a vector.
Here's your example rewritten to using std::vector
std::vector<int> masterArray;
int var = 0;
ifstream myfile("sample_10.txt");
if (myfile.is_open())
{
while(myfile.good())
{
string word;
while(getline(myfile, word))
{
count++;
}
cout << "count: " << count << endl;
masterArray.reserve(count); // will allocate at least count ints
myfile.clear();
myfile.seekg(0);
while(getline(myfile, word, '\n'))
{
cout << word << " ";
istringstream ( word ) >> var;
masterArray.push_back(var); // store the current word
}
}
}
I am creating a dynamic array inside a function. The code (posted below) runs without any problem. I am wondering if the way I have written is the right way to do it or if it will create problems in more complicated codes in the future. I am aware that the specific task my program (below) is trying to achieve is better effected with strings or vectors. But I created this artificial example to get my question across. however, if you strongly feel that dynamic arrays should be avoided, please feel free to share your opinion and the reasoning for it.
Result of my prior research: I was unable to find a coherent discussion on legality and morality of creating dynamic arrays using new [] and later deleting them in a different scope.
Thanks for your thoughts and insights.
My example code follows:
==========================
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
void getNonPunct(string _str, char* &_npcarr, int &_npsize);
int main()
{
string input_string;
char* npchar_arr;
int npsize;
cout << "Enter any string: ";
getline(cin, input_string);
getNonPunct(input_string, npchar_arr, npsize);
// Now display non-punctuation characters in the string
cout << "string with non-punctuation characters removed:\n";
for (int n = 0; n <= npsize - 1; n++)
cout << npchar_arr[n];
cout << "\n(" << npsize << ") non-punctuation characters\n";
// Now return the memory allocated with 'new' to heap
delete [] npchar_arr;
// Is it okay to 'delete' npchar_arr eve if it was created in the function
// getNonPunct() ?
return(0);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void getNonPunct(string _str, char* &_npcarr, int &_npsize)
//This void function takes an input array of strings containing arbitrary
//characters and returns a pointer to an array of characters containing only
//the non-punctuation characters in the input string. The number of
//non-punctuation characters are stored in size. Prior to the function call,
//int_arr and size are undefined. After the function call, char_arr points to
//the first location of an array of the non-punctuation character array.
//'size' is equal to the number of non-punctuation characters in the input
//string.
{
// First get the number of non-punctuation characters in the string
int str_len, npcount = 0;
str_len = static_cast<int>( _str.length() );
_npsize = 0;
for (int i = 0; i <= str_len - 1; i++)
{
if ( !ispunct(_str[i]) )
_npsize++;
}
// Now that you know how many non-punctuation characters are in the string,
// create a (dynamic) character array of _npsize.
_npcarr = new char [_npsize];
for (int k = 0; k <= str_len - 1; k++)
{
if ( !ispunct(_str[k]) )
_npcarr[npcount++] = _str[k];
}
return;
}
Is it valid? Yes. The array pointed to by npchar_arr exists until you destroy it and it is okay to destroy it using a delete[] expression in another function.
Is it a good idea? No. You would be much better off using a smart pointer that manages the lifetime of the object automatically, releasing you from the responsibility of delete[]ing the pointer manually yourself.
Consider using a std::unique_ptr<char[]> if your compiler and Standard Library support unique_ptr, or std::auto_ptr or std::shared_ptr if you cannot use unique_ptr (shared_ptr may also be found in Boost and C++ TR1).
Allocating in one scope and deleting in another is one of the major reasons for using dynamic allocation instead of an automatic local variable.
As James says, prefer to use smart pointers to track dynamically allocated objects.
The only constraint I can think of on allocation in one scope and deallocation in another is multi-component applications where different components are built with different compilers (or maybe different versions of the same compiler). On Windows, each compiler provides its own memory management library, and you shouldn't free memory from a different component than the one that allocated it. Or you can use Windows-provided memory management routines which are common to all compilers (e.g. HeapAlloc/HeapFree). On Linux, everyone uses the glibc-supplied malloc, free, new[], and delete[], so it isn't such an issue. For other OSes, you need to investigate.
This example is very trivial, but image the following modification of your code:
int main()
{
string input_string;
char* npchar_arr;
int npsize;
cout << "Enter any string: ";
getline(cin, input_string);
getNonPunct(input_string, npchar_arr, npsize);
// Now display non-punctuation characters in the string
cout << "string with non-punctuation characters removed:\n";
for (int n = 0; n <= npsize - 1; n++)
cout << npchar_arr[n];
cout << "\n(" << npsize << ") non-punctuation characters\n";
return(0); // WHOOPS! I JUST RETURNED AND DIDN'T FREE THE MEMORY
delete [] npchar_arr;
// Is it okay to 'delete' npchar_arr eve if it was created in the function
// getNonPunct() ?
return(0);
}
I just returned before freeing the memory, which results in a memory leak! Of course, you might be thinking that you would never do such a thing, but imagine a much more complex program, it is easy to make such a mistake as the above, and using smart pointers as the other answers suggest, would alleviate you of having to worry about such tasks.